diff options
author | Robb Matzke <matzke@llnl.gov> | 1997-10-20 23:14:35 (GMT) |
---|---|---|
committer | Robb Matzke <matzke@llnl.gov> | 1997-10-20 23:14:35 (GMT) |
commit | 56ad55117a89a423a9341d2f0c3912d4ad57ec6f (patch) | |
tree | dff0bada659180ac324d81a4d97f7bfb884f0ed6 | |
parent | dc4961d072249ddf39a7db7a945ea627c276d025 (diff) | |
download | hdf5-56ad55117a89a423a9341d2f0c3912d4ad57ec6f.zip hdf5-56ad55117a89a423a9341d2f0c3912d4ad57ec6f.tar.gz hdf5-56ad55117a89a423a9341d2f0c3912d4ad57ec6f.tar.bz2 |
[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.
-rw-r--r-- | MANIFEST | 6 | ||||
-rw-r--r-- | Makefile.in | 6 | ||||
-rw-r--r-- | acconfig.h | 5 | ||||
-rw-r--r-- | config/conclude.in | 4 | ||||
-rw-r--r-- | config/linux | 13 | ||||
-rwxr-xr-x | configure | 636 | ||||
-rw-r--r-- | configure.in | 18 | ||||
-rw-r--r-- | src/H5A.c | 2 | ||||
-rw-r--r-- | src/H5AC.c | 26 | ||||
-rw-r--r-- | src/H5ACprivate.h | 10 | ||||
-rw-r--r-- | src/H5Apublic.h | 2 | ||||
-rw-r--r-- | src/H5B.c | 369 | ||||
-rw-r--r-- | src/H5Bprivate.h | 35 | ||||
-rw-r--r-- | src/H5C.c | 20 | ||||
-rw-r--r-- | src/H5Cprivate.h | 2 | ||||
-rw-r--r-- | src/H5Cpublic.h | 1 | ||||
-rw-r--r-- | src/H5D.c | 8 | ||||
-rw-r--r-- | src/H5Distore.c | 740 | ||||
-rw-r--r-- | src/H5E.c | 5 | ||||
-rw-r--r-- | src/H5Epublic.h | 9 | ||||
-rw-r--r-- | src/H5F.c | 40 | ||||
-rw-r--r-- | src/H5Fistore.c | 740 | ||||
-rw-r--r-- | src/H5Fprivate.h | 11 | ||||
-rw-r--r-- | src/H5G.c | 799 | ||||
-rw-r--r-- | src/H5Gent.c | 2 | ||||
-rw-r--r-- | src/H5Gnode.c | 81 | ||||
-rw-r--r-- | src/H5Gpkg.h | 30 | ||||
-rw-r--r-- | src/H5Gprivate.h | 11 | ||||
-rw-r--r-- | src/H5Gpublic.h | 10 | ||||
-rw-r--r-- | src/H5Gshad.c | 86 | ||||
-rw-r--r-- | src/H5Gstab.c | 10 | ||||
-rw-r--r-- | src/H5H.c | 21 | ||||
-rw-r--r-- | src/H5O.c | 43 | ||||
-rw-r--r-- | src/H5Oistore.c | 271 | ||||
-rw-r--r-- | src/H5Oname.c | 14 | ||||
-rw-r--r-- | src/H5Oprivate.h | 21 | ||||
-rw-r--r-- | src/H5Osdtyp.c | 2 | ||||
-rw-r--r-- | src/H5config.h.in | 12 | ||||
-rw-r--r-- | src/H5private.h | 14 | ||||
-rw-r--r-- | src/Makefile.in | 10 | ||||
-rw-r--r-- | test/Makefile.in | 30 | ||||
-rw-r--r-- | test/istore.c | 431 | ||||
-rw-r--r-- | test/tstab.c | 12 |
43 files changed, 3949 insertions, 669 deletions
@@ -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 diff --git a/Makefile.in b/Makefile.in index a4ca408..3b2275a 100644 --- a/Makefile.in +++ b/Makefile.in @@ -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 diff --git a/acconfig.h b/acconfig.h new file mode 100644 index 0000000..e5be0c8 --- /dev/null +++ b/acconfig.h @@ -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 */ diff --git a/config/conclude.in b/config/conclude.in index b556c11..629d06c 100644 --- a/config/conclude.in +++ b/config/conclude.in @@ -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 diff --git a/config/linux b/config/linux index bf4b791..ec59f3f 100644 --- a/config/linux +++ b/config/linux @@ -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 @@ -2,8 +2,8 @@ # From configure.in Id: configure.in # Guess values for system-dependent variables and create Makefiles. -# Generated automatically using autoconf version 2.7 -# Copyright (C) 1992, 1993, 1994 Free Software Foundation, Inc. +# Generated automatically using autoconf version 2.12 +# Copyright (C) 1992, 93, 94, 95, 96 Free Software Foundation, Inc. # # This configure script is free software; the Free Software Foundation # gives unlimited permission to copy, distribute and modify it. @@ -50,6 +50,8 @@ mandir='${prefix}/man' # Initialize some other variables. subdirs= MFLAGS= MAKEFLAGS= +# Maximum number of lines to put in a shell here document. +ac_max_here_lines=12 ac_prev= for ac_option @@ -331,7 +333,7 @@ EOF verbose=yes ;; -version | --version | --versio | --versi | --vers) - echo "configure generated by autoconf version 2.7" + echo "configure generated by autoconf version 2.12" exit 0 ;; -with-* | --with-*) @@ -433,11 +435,14 @@ do done # NLS nuisances. -# Only set LANG and LC_ALL to C if already set. -# These must not be set unconditionally because not all systems understand -# e.g. LANG=C (notably SCO). -if test "${LC_ALL+set}" = set; then LC_ALL=C; export LC_ALL; fi +# Only set these to C if already set. These must not be set unconditionally +# because not all systems understand e.g. LANG=C (notably SCO). +# Fixing LC_MESSAGES prevents Solaris sh from translating var values in `set'! +# Non-C LC_CTYPE values break the ctype check. if test "${LANG+set}" = set; then LANG=C; export LANG; fi +if test "${LC_ALL+set}" = set; then LC_ALL=C; export LC_ALL; fi +if test "${LC_MESSAGES+set}" = set; then LC_MESSAGES=C; export LC_MESSAGES; fi +if test "${LC_CTYPE+set}" = set; then LC_CTYPE=C; export LC_CTYPE; fi # confdefs.h avoids OS command line length limits that DEFS can exceed. rm -rf conftest* confdefs.h @@ -496,12 +501,10 @@ fi ac_ext=c # CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options. -ac_cpp='echo $CPP $CPPFLAGS 1>&5; -$CPP $CPPFLAGS' -ac_compile='echo ${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5; -${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5 2>&5' -ac_link='echo ${CC-cc} -o conftest $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5; -${CC-cc} -o conftest $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5 2>&5' +ac_cpp='$CPP $CPPFLAGS' +ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5' +ac_link='${CC-cc} -o conftest $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5' +cross_compiling=$ac_cv_prog_cc_cross if (echo "testing\c"; echo 1,2,3) | grep c >/dev/null; then # Stardent Vistra SVR4 grep lacks -e, says ghazi@caip.rutgers.edu. @@ -543,6 +546,7 @@ else { echo "configure: error: can not run $ac_config_sub" 1>&2; exit 1; } fi echo $ac_n "checking host system type""... $ac_c" 1>&6 +echo "configure:550: checking host system type" >&5 host_alias=$host case "$host_alias" in @@ -557,15 +561,16 @@ NONE) esac host=`$ac_config_sub $host_alias` -host_cpu=`echo $host | sed 's/^\(.*\)-\(.*\)-\(.*\)$/\1/'` -host_vendor=`echo $host | sed 's/^\(.*\)-\(.*\)-\(.*\)$/\2/'` -host_os=`echo $host | sed 's/^\(.*\)-\(.*\)-\(.*\)$/\3/'` +host_cpu=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'` +host_vendor=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'` +host_os=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'` echo "$ac_t""$host" 1>&6 echo $ac_n "checking for cached host""... $ac_c" 1>&6 +echo "configure:574: checking for cached host" >&5 if eval "test \"`echo '$''{'hdf5_cv_host'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -584,6 +589,7 @@ fi echo $ac_n "checking for site config file""... $ac_c" 1>&6 +echo "configure:593: checking for site config file" >&5 site_config="none" for f in $host $host_vendor-$host_os $host_os; do if test -f config/$f; then @@ -601,6 +607,7 @@ fi # Extract the first word of "gcc", so it can be a program name with args. set dummy gcc; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:611: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -616,7 +623,6 @@ else fi done IFS="$ac_save_ifs" - test -z "$ac_cv_prog_CC" && ac_cv_prog_CC="cc" fi fi CC="$ac_cv_prog_CC" @@ -626,8 +632,98 @@ else echo "$ac_t""no" 1>&6 fi +if test -z "$CC"; then + # Extract the first word of "cc", so it can be a program name with args. +set dummy cc; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:640: checking for $ac_word" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:" + ac_prog_rejected=no + for ac_dir in $PATH; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + if test "$ac_dir/$ac_word" = "/usr/ucb/cc"; then + ac_prog_rejected=yes + continue + fi + ac_cv_prog_CC="cc" + break + fi + done + IFS="$ac_save_ifs" +if test $ac_prog_rejected = yes; then + # We found a bogon in the path, so make sure we never use it. + set dummy $ac_cv_prog_CC + shift + if test $# -gt 0; then + # We chose a different compiler from the bogus one. + # However, it has the same basename, so the bogon will be chosen + # first if we set CC to just the basename; use the full file name. + shift + set dummy "$ac_dir/$ac_word" "$@" + shift + ac_cv_prog_CC="$@" + fi +fi +fi +fi +CC="$ac_cv_prog_CC" +if test -n "$CC"; then + echo "$ac_t""$CC" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + + test -z "$CC" && { echo "configure: error: no acceptable cc found in \$PATH" 1>&2; exit 1; } +fi + +echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works""... $ac_c" 1>&6 +echo "configure:688: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works" >&5 + +ac_ext=c +# CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options. +ac_cpp='$CPP $CPPFLAGS' +ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5' +ac_link='${CC-cc} -o conftest $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5' +cross_compiling=$ac_cv_prog_cc_cross + +cat > conftest.$ac_ext <<EOF +#line 698 "configure" +#include "confdefs.h" +main(){return(0);} +EOF +if { (eval echo configure:702: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then + ac_cv_prog_cc_works=yes + # If we can't run a trivial program, we are probably using a cross compiler. + if (./conftest; exit) 2>/dev/null; then + ac_cv_prog_cc_cross=no + else + ac_cv_prog_cc_cross=yes + fi +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + ac_cv_prog_cc_works=no +fi +rm -fr conftest* + +echo "$ac_t""$ac_cv_prog_cc_works" 1>&6 +if test $ac_cv_prog_cc_works = no; then + { echo "configure: error: installation or configuration problem: C compiler cannot create executables." 1>&2; exit 1; } +fi +echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler""... $ac_c" 1>&6 +echo "configure:722: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler" >&5 +echo "$ac_t""$ac_cv_prog_cc_cross" 1>&6 +cross_compiling=$ac_cv_prog_cc_cross echo $ac_n "checking whether we are using GNU C""... $ac_c" 1>&6 +echo "configure:727: checking whether we are using GNU C" >&5 if eval "test \"`echo '$''{'ac_cv_prog_gcc'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -636,7 +732,7 @@ else yes; #endif EOF -if ${CC-cc} -E conftest.c 2>&5 | egrep yes >/dev/null 2>&1; then +if { ac_try='${CC-cc} -E conftest.c'; { (eval echo configure:736: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then ac_cv_prog_gcc=yes else ac_cv_prog_gcc=no @@ -644,29 +740,34 @@ fi fi echo "$ac_t""$ac_cv_prog_gcc" 1>&6 + if test $ac_cv_prog_gcc = yes; then GCC=yes - if test "${CFLAGS+set}" != set; then - echo $ac_n "checking whether ${CC-cc} accepts -g""... $ac_c" 1>&6 -if eval "test \"`echo '$''{'ac_cv_prog_gcc_g'+set}'`\" = set"; then + ac_test_CFLAGS="${CFLAGS+set}" + ac_save_CFLAGS="$CFLAGS" + CFLAGS= + echo $ac_n "checking whether ${CC-cc} accepts -g""... $ac_c" 1>&6 +echo "configure:751: checking whether ${CC-cc} accepts -g" >&5 +if eval "test \"`echo '$''{'ac_cv_prog_cc_g'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else echo 'void f(){}' > conftest.c if test -z "`${CC-cc} -g -c conftest.c 2>&1`"; then - ac_cv_prog_gcc_g=yes + ac_cv_prog_cc_g=yes else - ac_cv_prog_gcc_g=no + ac_cv_prog_cc_g=no fi rm -f conftest* fi -echo "$ac_t""$ac_cv_prog_gcc_g" 1>&6 - if test $ac_cv_prog_gcc_g = yes; then - CFLAGS="-g -O" - else - CFLAGS="-O" - fi +echo "$ac_t""$ac_cv_prog_cc_g" 1>&6 + if test "$ac_test_CFLAGS" = set; then + CFLAGS="$ac_save_CFLAGS" + elif test $ac_cv_prog_cc_g = yes; then + CFLAGS="-g -O2" + else + CFLAGS="-O2" fi else GCC= @@ -674,7 +775,8 @@ else fi echo $ac_n "checking whether ${MAKE-make} sets \${MAKE}""... $ac_c" 1>&6 -set dummy ${MAKE-make}; ac_make=$2 +echo "configure:779: checking whether ${MAKE-make} sets \${MAKE}" >&5 +set dummy ${MAKE-make}; ac_make=`echo "$2" | sed 'y%./+-%__p_%'` if eval "test \"`echo '$''{'ac_cv_prog_make_${ac_make}_set'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -710,11 +812,12 @@ fi # SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff" # ./install, which can be erroneously created by make from ./install.sh. echo $ac_n "checking for a BSD compatible install""... $ac_c" 1>&6 +echo "configure:816: checking for a BSD compatible install" >&5 if test -z "$INSTALL"; then if eval "test \"`echo '$''{'ac_cv_path_install'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else - IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:" + IFS="${IFS= }"; ac_save_IFS="$IFS"; IFS="${IFS}:" for ac_dir in $PATH; do # Account for people who put trailing slashes in PATH elements. case "$ac_dir/" in @@ -737,7 +840,7 @@ else ;; esac done - IFS="$ac_save_ifs" + IFS="$ac_save_IFS" fi if test "${ac_cv_path_install+set}" = set; then @@ -761,6 +864,7 @@ test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644' # Extract the first word of "ranlib", so it can be a program name with args. set dummy ranlib; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +echo "configure:868: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_prog_RANLIB'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -788,6 +892,7 @@ fi echo $ac_n "checking for GNU Make""... $ac_c" 1>&6 +echo "configure:896: checking for GNU Make" >&5 if test "`${MAKE-make} --version -f /dev/null 2>/dev/null |\ sed -n 1p|cut -c1-8`" = "GNU Make"; then echo "$ac_t""yes" 1>&6 @@ -802,6 +907,7 @@ fi echo $ac_n "checking how to run the C preprocessor""... $ac_c" 1>&6 +echo "configure:911: checking how to run the C preprocessor" >&5 # On Suns, sometimes $CPP names a directory. if test -n "$CPP" && test -d "$CPP"; then CPP= @@ -816,31 +922,37 @@ else # On the NeXT, cc -E runs the code through the compiler's parser, # not just through cpp. cat > conftest.$ac_ext <<EOF -#line 820 "configure" +#line 926 "configure" #include "confdefs.h" #include <assert.h> Syntax Error EOF -eval "$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +{ (eval echo configure:932: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out` if test -z "$ac_err"; then : else echo "$ac_err" >&5 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 rm -rf conftest* CPP="${CC-cc} -E -traditional-cpp" cat > conftest.$ac_ext <<EOF -#line 834 "configure" +#line 943 "configure" #include "confdefs.h" #include <assert.h> Syntax Error EOF -eval "$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +{ (eval echo configure:949: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out` if test -z "$ac_err"; then : else echo "$ac_err" >&5 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 rm -rf conftest* CPP=/lib/cpp fi @@ -855,51 +967,29 @@ else fi echo "$ac_t""$CPP" 1>&6 -# If we cannot run a trivial program, we must be cross compiling. -echo $ac_n "checking whether cross-compiling""... $ac_c" 1>&6 -if eval "test \"`echo '$''{'ac_cv_c_cross'+set}'`\" = set"; then - echo $ac_n "(cached) $ac_c" 1>&6 -else - if test "$cross_compiling" = yes; then - ac_cv_c_cross=yes -else -cat > conftest.$ac_ext <<EOF -#line 868 "configure" -#include "confdefs.h" -main(){return(0);} -EOF -eval $ac_link -if test -s conftest && (./conftest; exit) 2>/dev/null; then - ac_cv_c_cross=no -else - ac_cv_c_cross=yes -fi -fi -rm -fr conftest* -fi - -echo "$ac_t""$ac_cv_c_cross" 1>&6 -cross_compiling=$ac_cv_c_cross - echo $ac_n "checking for ANSI C header files""... $ac_c" 1>&6 +echo "configure:972: checking for ANSI C header files" >&5 if eval "test \"`echo '$''{'ac_cv_header_stdc'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <<EOF -#line 890 "configure" +#line 977 "configure" #include "confdefs.h" #include <stdlib.h> #include <stdarg.h> #include <string.h> #include <float.h> EOF -eval "$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" +{ (eval echo configure:985: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out` if test -z "$ac_err"; then rm -rf conftest* ac_cv_header_stdc=yes else echo "$ac_err" >&5 + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 rm -rf conftest* ac_cv_header_stdc=no fi @@ -908,7 +998,7 @@ rm -f conftest* if test $ac_cv_header_stdc = yes; then # SunOS 4.x string.h does not declare mem*, contrary to ANSI. cat > conftest.$ac_ext <<EOF -#line 912 "configure" +#line 1002 "configure" #include "confdefs.h" #include <string.h> EOF @@ -926,7 +1016,7 @@ fi if test $ac_cv_header_stdc = yes; then # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. cat > conftest.$ac_ext <<EOF -#line 930 "configure" +#line 1020 "configure" #include "confdefs.h" #include <stdlib.h> EOF @@ -946,8 +1036,8 @@ if test $ac_cv_header_stdc = yes; then if test "$cross_compiling" = yes; then : else -cat > conftest.$ac_ext <<EOF -#line 951 "configure" + cat > conftest.$ac_ext <<EOF +#line 1041 "configure" #include "confdefs.h" #include <ctype.h> #define ISLOWER(c) ('a' <= (c) && (c) <= 'z') @@ -958,15 +1048,19 @@ if (XOR (islower (i), ISLOWER (i)) || toupper (i) != TOUPPER (i)) exit(2); exit (0); } EOF -eval $ac_link -if test -s conftest && (./conftest; exit) 2>/dev/null; then +if { (eval echo configure:1052: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null +then : else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -fr conftest* ac_cv_header_stdc=no fi -fi rm -fr conftest* fi + +fi fi echo "$ac_t""$ac_cv_header_stdc" 1>&6 @@ -981,19 +1075,21 @@ fi echo $ac_n "checking for off_t""... $ac_c" 1>&6 +echo "configure:1079: checking for off_t" >&5 if eval "test \"`echo '$''{'ac_cv_type_off_t'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <<EOF -#line 989 "configure" +#line 1084 "configure" #include "confdefs.h" #include <sys/types.h> #if STDC_HEADERS #include <stdlib.h> +#include <stddef.h> #endif EOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | - egrep "off_t" >/dev/null 2>&1; then + egrep "off_t[^a-zA-Z_0-9]" >/dev/null 2>&1; then rm -rf conftest* ac_cv_type_off_t=yes else @@ -1012,19 +1108,21 @@ EOF fi echo $ac_n "checking for size_t""... $ac_c" 1>&6 +echo "configure:1112: checking for size_t" >&5 if eval "test \"`echo '$''{'ac_cv_type_size_t'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <<EOF -#line 1020 "configure" +#line 1117 "configure" #include "confdefs.h" #include <sys/types.h> #if STDC_HEADERS #include <stdlib.h> +#include <stddef.h> #endif EOF if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | - egrep "size_t" >/dev/null 2>&1; then + egrep "size_t[^a-zA-Z_0-9]" >/dev/null 2>&1; then rm -rf conftest* ac_cv_type_size_t=yes else @@ -1046,58 +1144,60 @@ fi echo $ac_n "checking whether byte ordering is bigendian""... $ac_c" 1>&6 +echo "configure:1148: checking whether byte ordering is bigendian" >&5 if eval "test \"`echo '$''{'ac_cv_c_bigendian'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else ac_cv_c_bigendian=unknown # See if sys/param.h defines the BYTE_ORDER macro. cat > conftest.$ac_ext <<EOF -#line 1056 "configure" +#line 1155 "configure" #include "confdefs.h" #include <sys/types.h> #include <sys/param.h> -int main() { return 0; } -int t() { +int main() { #if !BYTE_ORDER || !BIG_ENDIAN || !LITTLE_ENDIAN bogus endian macros #endif ; return 0; } EOF -if eval $ac_compile; then +if { (eval echo configure:1166: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* # It does; now see whether it defined to BIG_ENDIAN or not. cat > conftest.$ac_ext <<EOF -#line 1072 "configure" +#line 1170 "configure" #include "confdefs.h" #include <sys/types.h> #include <sys/param.h> -int main() { return 0; } -int t() { +int main() { #if BYTE_ORDER != BIG_ENDIAN not big endian #endif ; return 0; } EOF -if eval $ac_compile; then +if { (eval echo configure:1181: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_cv_c_bigendian=yes else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 rm -rf conftest* ac_cv_c_bigendian=no fi rm -f conftest* - +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 fi rm -f conftest* - if test $ac_cv_c_bigendian = unknown; then if test "$cross_compiling" = yes; then { echo "configure: error: can not run test program while cross compiling" 1>&2; exit 1; } else -cat > conftest.$ac_ext <<EOF -#line 1101 "configure" + cat > conftest.$ac_ext <<EOF +#line 1201 "configure" #include "confdefs.h" main () { /* Are we little or big endian? From Harbison&Steele. */ @@ -1110,15 +1210,19 @@ main () { exit (u.c[sizeof (long) - 1] == 1); } EOF -eval $ac_link -if test -s conftest && (./conftest; exit) 2>/dev/null; then +if { (eval echo configure:1214: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null +then ac_cv_c_bigendian=no else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -fr conftest* ac_cv_c_bigendian=yes fi -fi rm -fr conftest* fi + +fi fi echo "$ac_t""$ac_cv_c_bigendian" 1>&6 @@ -1130,14 +1234,15 @@ EOF fi echo $ac_n "checking size of short""... $ac_c" 1>&6 +echo "configure:1238: checking size of short" >&5 if eval "test \"`echo '$''{'ac_cv_sizeof_short'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else if test "$cross_compiling" = yes; then ac_cv_sizeof_short=2 else -cat > conftest.$ac_ext <<EOF -#line 1141 "configure" + cat > conftest.$ac_ext <<EOF +#line 1246 "configure" #include "confdefs.h" #include <stdio.h> main() @@ -1148,15 +1253,19 @@ main() exit(0); } EOF -eval $ac_link -if test -s conftest && (./conftest; exit) 2>/dev/null; then +if { (eval echo configure:1257: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null +then ac_cv_sizeof_short=`cat conftestval` else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -fr conftest* ac_cv_sizeof_short=0 fi -fi rm -fr conftest* fi + +fi echo "$ac_t""$ac_cv_sizeof_short" 1>&6 cat >> confdefs.h <<EOF #define SIZEOF_SHORT $ac_cv_sizeof_short @@ -1164,14 +1273,15 @@ EOF echo $ac_n "checking size of int""... $ac_c" 1>&6 +echo "configure:1277: checking size of int" >&5 if eval "test \"`echo '$''{'ac_cv_sizeof_int'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else if test "$cross_compiling" = yes; then ac_cv_sizeof_int=4 else -cat > conftest.$ac_ext <<EOF -#line 1175 "configure" + cat > conftest.$ac_ext <<EOF +#line 1285 "configure" #include "confdefs.h" #include <stdio.h> main() @@ -1182,15 +1292,19 @@ main() exit(0); } EOF -eval $ac_link -if test -s conftest && (./conftest; exit) 2>/dev/null; then +if { (eval echo configure:1296: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null +then ac_cv_sizeof_int=`cat conftestval` else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -fr conftest* ac_cv_sizeof_int=0 fi -fi rm -fr conftest* fi + +fi echo "$ac_t""$ac_cv_sizeof_int" 1>&6 cat >> confdefs.h <<EOF #define SIZEOF_INT $ac_cv_sizeof_int @@ -1198,14 +1312,15 @@ EOF echo $ac_n "checking size of long""... $ac_c" 1>&6 +echo "configure:1316: checking size of long" >&5 if eval "test \"`echo '$''{'ac_cv_sizeof_long'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else if test "$cross_compiling" = yes; then ac_cv_sizeof_long=4 else -cat > conftest.$ac_ext <<EOF -#line 1209 "configure" + cat > conftest.$ac_ext <<EOF +#line 1324 "configure" #include "confdefs.h" #include <stdio.h> main() @@ -1216,15 +1331,19 @@ main() exit(0); } EOF -eval $ac_link -if test -s conftest && (./conftest; exit) 2>/dev/null; then +if { (eval echo configure:1335: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null +then ac_cv_sizeof_long=`cat conftestval` else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -fr conftest* ac_cv_sizeof_long=0 fi -fi rm -fr conftest* fi + +fi echo "$ac_t""$ac_cv_sizeof_long" 1>&6 cat >> confdefs.h <<EOF #define SIZEOF_LONG $ac_cv_sizeof_long @@ -1232,14 +1351,15 @@ EOF echo $ac_n "checking size of long long""... $ac_c" 1>&6 +echo "configure:1355: checking size of long long" >&5 if eval "test \"`echo '$''{'ac_cv_sizeof_long_long'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else if test "$cross_compiling" = yes; then ac_cv_sizeof_long_long=8 else -cat > conftest.$ac_ext <<EOF -#line 1243 "configure" + cat > conftest.$ac_ext <<EOF +#line 1363 "configure" #include "confdefs.h" #include <stdio.h> main() @@ -1250,15 +1370,19 @@ main() exit(0); } EOF -eval $ac_link -if test -s conftest && (./conftest; exit) 2>/dev/null; then +if { (eval echo configure:1374: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null +then ac_cv_sizeof_long_long=`cat conftestval` else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -fr conftest* ac_cv_sizeof_long_long=0 fi -fi rm -fr conftest* fi + +fi echo "$ac_t""$ac_cv_sizeof_long_long" 1>&6 cat >> confdefs.h <<EOF #define SIZEOF_LONG_LONG $ac_cv_sizeof_long_long @@ -1266,14 +1390,15 @@ EOF echo $ac_n "checking size of float""... $ac_c" 1>&6 +echo "configure:1394: checking size of float" >&5 if eval "test \"`echo '$''{'ac_cv_sizeof_float'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else if test "$cross_compiling" = yes; then ac_cv_sizeof_float=4 else -cat > conftest.$ac_ext <<EOF -#line 1277 "configure" + cat > conftest.$ac_ext <<EOF +#line 1402 "configure" #include "confdefs.h" #include <stdio.h> main() @@ -1284,15 +1409,19 @@ main() exit(0); } EOF -eval $ac_link -if test -s conftest && (./conftest; exit) 2>/dev/null; then +if { (eval echo configure:1413: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null +then ac_cv_sizeof_float=`cat conftestval` else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -fr conftest* ac_cv_sizeof_float=0 fi -fi rm -fr conftest* fi + +fi echo "$ac_t""$ac_cv_sizeof_float" 1>&6 cat >> confdefs.h <<EOF #define SIZEOF_FLOAT $ac_cv_sizeof_float @@ -1300,14 +1429,15 @@ EOF echo $ac_n "checking size of double""... $ac_c" 1>&6 +echo "configure:1433: checking size of double" >&5 if eval "test \"`echo '$''{'ac_cv_sizeof_double'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else if test "$cross_compiling" = yes; then ac_cv_sizeof_double=8 else -cat > conftest.$ac_ext <<EOF -#line 1311 "configure" + cat > conftest.$ac_ext <<EOF +#line 1441 "configure" #include "confdefs.h" #include <stdio.h> main() @@ -1318,15 +1448,19 @@ main() exit(0); } EOF -eval $ac_link -if test -s conftest && (./conftest; exit) 2>/dev/null; then +if { (eval echo configure:1452: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null +then ac_cv_sizeof_double=`cat conftestval` else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -fr conftest* ac_cv_sizeof_double=0 fi -fi rm -fr conftest* fi + +fi echo "$ac_t""$ac_cv_sizeof_double" 1>&6 cat >> confdefs.h <<EOF #define SIZEOF_DOUBLE $ac_cv_sizeof_double @@ -1337,6 +1471,170 @@ EOF +echo $ac_n "checking for working const""... $ac_c" 1>&6 +echo "configure:1476: checking for working const" >&5 +if eval "test \"`echo '$''{'ac_cv_c_const'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext <<EOF +#line 1481 "configure" +#include "confdefs.h" + +int main() { + +/* Ultrix mips cc rejects this. */ +typedef int charset[2]; const charset x; +/* SunOS 4.1.1 cc rejects this. */ +char const *const *ccp; +char **p; +/* NEC SVR4.0.2 mips cc rejects this. */ +struct point {int x, y;}; +static struct point const zero = {0,0}; +/* AIX XL C 1.02.0.0 rejects this. + It does not let you subtract one const X* pointer from another in an arm + of an if-expression whose if-part is not a constant expression */ +const char *g = "string"; +ccp = &g + (g ? g-g : 0); +/* HPUX 7.0 cc rejects these. */ +++ccp; +p = (char**) ccp; +ccp = (char const *const *) p; +{ /* SCO 3.2v4 cc rejects this. */ + char *t; + char const *s = 0 ? (char *) 0 : (char const *) 0; + + *t++ = 0; +} +{ /* Someone thinks the Sun supposedly-ANSI compiler will reject this. */ + int x[] = {25, 17}; + const int *foo = &x[0]; + ++foo; +} +{ /* Sun SC1.0 ANSI compiler rejects this -- but not the above. */ + typedef const int *iptr; + iptr p = 0; + ++p; +} +{ /* AIX XL C 1.02.0.0 rejects this saying + "k.c", line 2.27: 1506-025 (S) Operand must be a modifiable lvalue. */ + struct s { int j; const int *ap[3]; }; + struct s *b; b->j = 5; +} +{ /* ULTRIX-32 V3.1 (Rev 9) vcc rejects this */ + const int foo = 10; +} + +; return 0; } +EOF +if { (eval echo configure:1530: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then + rm -rf conftest* + ac_cv_c_const=yes +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + ac_cv_c_const=no +fi +rm -f conftest* +fi + +echo "$ac_t""$ac_cv_c_const" 1>&6 +if test $ac_cv_c_const = no; then + cat >> confdefs.h <<\EOF +#define const +EOF + +fi + +echo $ac_n "checking for inline""... $ac_c" 1>&6 +echo "configure:1551: checking for inline" >&5 +if eval "test \"`echo '$''{'ac_cv_c_inline'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + ac_cv_c_inline=no +for ac_kw in inline __inline__ __inline; do + cat > conftest.$ac_ext <<EOF +#line 1558 "configure" +#include "confdefs.h" + +int main() { +} $ac_kw foo() { +; return 0; } +EOF +if { (eval echo configure:1565: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then + rm -rf conftest* + ac_cv_c_inline=$ac_kw; break +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 +fi +rm -f conftest* +done + +fi + +echo "$ac_t""$ac_cv_c_inline" 1>&6 +case "$ac_cv_c_inline" in + inline | yes) ;; + no) cat >> confdefs.h <<\EOF +#define inline +EOF + ;; + *) cat >> confdefs.h <<EOF +#define inline $ac_cv_c_inline +EOF + ;; +esac + + +echo $ac_n "checking for __attribute__ extension""... $ac_c" 1>&6 +echo "configure:1592: checking for __attribute__ extension" >&5 +cat > conftest.$ac_ext <<EOF +#line 1594 "configure" +#include "confdefs.h" + +int main() { +int __attribute__((unused)) f(void){return 1;} +; return 0; } +EOF +if { (eval echo configure:1601: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then + rm -rf conftest* + cat >> confdefs.h <<\EOF +#define HAVE_ATTRIBUTE 1 +EOF + echo "$ac_t""yes" 1>&6 +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + echo "$ac_t""no" 1>&6 +fi +rm -f conftest* + +echo $ac_n "checking for __FUNCTION__ extension""... $ac_c" 1>&6 +echo "configure:1616: checking for __FUNCTION__ extension" >&5 +cat > conftest.$ac_ext <<EOF +#line 1618 "configure" +#include "confdefs.h" + +int main() { +int f(void){return __FUNCTION__;} +; return 0; } +EOF +if { (eval echo configure:1625: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then + rm -rf conftest* + cat >> confdefs.h <<\EOF +#define HAVE_FUNCTION 1 +EOF + echo "$ac_t""yes" 1>&6 +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + echo "$ac_t""no" 1>&6 +fi +rm -f conftest* + COMMENCE=config/commence @@ -1380,11 +1678,25 @@ cat > confcache <<\EOF # --recheck option to rerun configure. # EOF +# The following way of writing the cache mishandles newlines in values, +# but we know of no workaround that is simple, portable, and efficient. +# So, don't put newlines in cache variables' values. # Ultrix sh set writes to stderr and can't be redirected directly, # and sets the high bit in the cache file unless we assign to the vars. (set) 2>&1 | - sed -n "s/^\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\)=\(.*\)/\1=\${\1='\2'}/p" \ - >> confcache + case `(ac_space=' '; set) 2>&1` in + *ac_space=\ *) + # `set' does not quote correctly, so add quotes (double-quote substitution + # turns \\\\ into \\, and sed turns \\ into \). + sed -n \ + -e "s/'/'\\\\''/g" \ + -e "s/^\\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\\)=\\(.*\\)/\\1=\${\\1='\\2'}/p" + ;; + *) + # `set' quotes correctly as required by POSIX, so do not add quotes. + sed -n -e 's/^\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\)=\(.*\)/\1=${\1=\2}/p' + ;; + esac >> confcache if cmp -s $cache_file confcache; then : else @@ -1439,7 +1751,7 @@ do echo "running \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion" exec \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion ;; -version | --version | --versio | --versi | --vers | --ver | --ve | --v) - echo "$CONFIG_STATUS generated by autoconf version 2.7" + echo "$CONFIG_STATUS generated by autoconf version 2.12" exit 0 ;; -help | --help | --hel | --he | --h) echo "\$ac_cs_usage"; exit 0 ;; @@ -1503,6 +1815,42 @@ s%@ROOT@%$ROOT%g CEOF EOF + +cat >> $CONFIG_STATUS <<\EOF + +# Split the substitutions into bite-sized pieces for seds with +# small command number limits, like on Digital OSF/1 and HP-UX. +ac_max_sed_cmds=90 # Maximum number of lines to put in a sed script. +ac_file=1 # Number of current file. +ac_beg=1 # First line for current file. +ac_end=$ac_max_sed_cmds # Line after last line for current file. +ac_more_lines=: +ac_sed_cmds="" +while $ac_more_lines; do + if test $ac_beg -gt 1; then + sed "1,${ac_beg}d; ${ac_end}q" conftest.subs > conftest.s$ac_file + else + sed "${ac_end}q" conftest.subs > conftest.s$ac_file + fi + if test ! -s conftest.s$ac_file; then + ac_more_lines=false + rm -f conftest.s$ac_file + else + if test -z "$ac_sed_cmds"; then + ac_sed_cmds="sed -f conftest.s$ac_file" + else + ac_sed_cmds="$ac_sed_cmds | sed -f conftest.s$ac_file" + fi + ac_file=`expr $ac_file + 1` + ac_beg=$ac_end + ac_end=`expr $ac_end + $ac_max_sed_cmds` + fi +done +if test -z "$ac_sed_cmds"; then + ac_sed_cmds=cat +fi +EOF + cat >> $CONFIG_STATUS <<EOF CONFIG_FILES=\${CONFIG_FILES-"config/depend config/commence config/conclude \ @@ -1510,14 +1858,14 @@ CONFIG_FILES=\${CONFIG_FILES-"config/depend config/commence config/conclude \ EOF cat >> $CONFIG_STATUS <<\EOF for ac_file in .. $CONFIG_FILES; do if test "x$ac_file" != x..; then - # Support "outfile[:infile]", defaulting infile="outfile.in". + # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in". case "$ac_file" in - *:*) ac_file_in=`echo "$ac_file"|sed 's%.*:%%'` + *:*) ac_file_in=`echo "$ac_file"|sed 's%[^:]*:%%'` ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;; *) ac_file_in="${ac_file}.in" ;; esac - # Adjust relative srcdir, etc. for subdirectories. + # Adjust a relative srcdir, top_srcdir, and INSTALL for subdirectories. # Remove last slash and all that follows it. Not all systems have dirname. ac_dir=`echo $ac_file|sed 's%/[^/][^/]*$%%'` @@ -1545,6 +1893,7 @@ for ac_file in .. $CONFIG_FILES; do if test "x$ac_file" != x..; then [/$]*) INSTALL="$ac_given_INSTALL" ;; *) INSTALL="$ac_dots$ac_given_INSTALL" ;; esac + echo creating "$ac_file" rm -f "$ac_file" configure_input="Generated automatically from `echo $ac_file_in|sed 's%.*/%%'` by configure." @@ -1553,14 +1902,16 @@ for ac_file in .. $CONFIG_FILES; do if test "x$ac_file" != x..; then # $configure_input" ;; *) ac_comsub= ;; esac + + ac_file_inputs=`echo $ac_file_in|sed -e "s%^%$ac_given_srcdir/%" -e "s%:% $ac_given_srcdir/%g"` sed -e "$ac_comsub s%@configure_input@%$configure_input%g s%@srcdir@%$srcdir%g s%@top_srcdir@%$top_srcdir%g s%@INSTALL@%$INSTALL%g -" -f conftest.subs $ac_given_srcdir/$ac_file_in > $ac_file +" $ac_file_inputs | (eval "$ac_sed_cmds") > $ac_file fi; done -rm -f conftest.subs +rm -f conftest.s* # These sed commands are passed to sed as "A NAME B NAME C VALUE D", where # NAME is the cpp macro being defined and VALUE is the value it is being given. @@ -1581,11 +1932,17 @@ ac_eB='$%\1#\2define\3' ac_eC=' ' ac_eD='%g' -CONFIG_HEADERS=${CONFIG_HEADERS-"src/H5config.h"} +if test "${CONFIG_HEADERS+set}" != set; then +EOF +cat >> $CONFIG_STATUS <<EOF + CONFIG_HEADERS="src/H5config.h" +EOF +cat >> $CONFIG_STATUS <<\EOF +fi for ac_file in .. $CONFIG_HEADERS; do if test "x$ac_file" != x..; then - # Support "outfile[:infile]", defaulting infile="outfile.in". + # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in". case "$ac_file" in - *:*) ac_file_in=`echo "$ac_file"|sed 's%.*:%%'` + *:*) ac_file_in=`echo "$ac_file"|sed 's%[^:]*:%%'` ac_file=`echo "$ac_file"|sed 's%:.*%%'` ;; *) ac_file_in="${ac_file}.in" ;; esac @@ -1593,7 +1950,8 @@ for ac_file in .. $CONFIG_HEADERS; do if test "x$ac_file" != x..; then echo creating $ac_file rm -f conftest.frag conftest.in conftest.out - cp $ac_given_srcdir/$ac_file_in conftest.in + ac_file_inputs=`echo $ac_file_in|sed -e "s%^%$ac_given_srcdir/%" -e "s%:% $ac_given_srcdir/%g"` + cat $ac_file_inputs > conftest.in EOF @@ -1605,7 +1963,7 @@ rm -f conftest.vals cat > conftest.hdr <<\EOF s/[\\&%]/\\&/g s%[\\$`]%\\&%g -s%#define \([A-Za-z_][A-Za-z0-9_]*\) \(.*\)%${ac_dA}\1${ac_dB}\1${ac_dC}\2${ac_dD}%gp +s%#define \([A-Za-z_][A-Za-z0-9_]*\) *\(.*\)%${ac_dA}\1${ac_dB}\1${ac_dC}\2${ac_dD}%gp s%ac_d%ac_u%gp s%ac_u%ac_e%gp EOF @@ -1621,8 +1979,6 @@ EOF # Break up conftest.vals because some shells have a limit on # the size of here documents, and old seds have small limits too. -# Maximum number of lines to put in a single here document. -ac_max_here_lines=12 rm -f conftest.tail while : @@ -1653,12 +2009,22 @@ cat >> $CONFIG_STATUS <<\EOF echo "$ac_file is unchanged" rm -f conftest.h else + # Remove last slash and all that follows it. Not all systems have dirname. + ac_dir=`echo $ac_file|sed 's%/[^/][^/]*$%%'` + if test "$ac_dir" != "$ac_file" && test "$ac_dir" != .; then + # The file is in a subdirectory. + test ! -d "$ac_dir" && mkdir "$ac_dir" + fi rm -f $ac_file mv conftest.h $ac_file fi fi; done +EOF +cat >> $CONFIG_STATUS <<EOF +EOF +cat >> $CONFIG_STATUS <<\EOF exit 0 EOF diff --git a/configure.in b/configure.in index 1d7ee2f..9e7cc44 100644 --- a/configure.in +++ b/configure.in @@ -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)) @@ -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 */ @@ -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: diff --git a/src/H5ACprivate.h b/src/H5ACprivate.h index a028d9c..25549ff 100644 --- a/src/H5ACprivate.h +++ b/src/H5ACprivate.h @@ -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 */ diff --git a/src/H5Apublic.h b/src/H5Apublic.h index 36cceed..efae778 100644 --- a/src/H5Apublic.h +++ b/src/H5Apublic.h @@ -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 */ ); /****************************************************************************** @@ -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, <_key_changed, + child = H5B_insert_helper (f, addr, type, &anchor, lt_key, <_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); - } - - /* right key */ - if (!bt->key[idx+1].nkey && H5B_decode_key (f, bt, idx+1)<0) { - HGOTO_ERROR (H5E_BTREE, H5E_CANTDECODE, FAIL); + if (H5B_decode_keys (f, bt, idx)<0) { + HRETURN_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) { + if (0==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. + * The value being inserted will be the only value in this tree. We + * must necessarily be at level zero. */ - 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) { + 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 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 { - child_addr = (type->insert)(f, bt->child[idx], &anchor, + /* + * 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 || my_ins<0) { + /* Insertion failed */ + HGOTO_ERROR (H5E_BTREE, H5E_CANTINSERT, FAIL); } - if (child_addr<0) 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) { + /* + * 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) { /* - * If the child split and the left node is anchored, then the new + * 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); } diff --git a/src/H5Bprivate.h b/src/H5Bprivate.h index 7814eeb..05e2e56 100644 --- a/src/H5Bprivate.h +++ b/src/H5Bprivate.h @@ -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); @@ -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; diff --git a/src/H5Cprivate.h b/src/H5Cprivate.h index 675fba6..168b253 100644 --- a/src/H5Cprivate.h +++ b/src/H5Cprivate.h @@ -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 */ \ diff --git a/src/H5Cpublic.h b/src/H5Cpublic.h index 08e7656..4d2fd7d 100644 --- a/src/H5Cpublic.h +++ b/src/H5Cpublic.h @@ -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 */ @@ -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; diff --git a/src/H5Distore.c b/src/H5Distore.c new file mode 100644 index 0000000..b52288c --- /dev/null +++ b/src/H5Distore.c @@ -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); +} + @@ -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"}, }; diff --git a/src/H5Epublic.h b/src/H5Epublic.h index bde74e5..abb6e3c 100644 --- a/src/H5Epublic.h +++ b/src/H5Epublic.h @@ -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; @@ -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) { @@ -573,6 +579,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 * with hard or soft links) it doesn't work to compare files based only on @@ -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; diff --git a/src/H5Fistore.c b/src/H5Fistore.c new file mode 100644 index 0000000..b52288c --- /dev/null +++ b/src/H5Fistore.c @@ -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); +} + diff --git a/src/H5Fprivate.h b/src/H5Fprivate.h index 81f43ce..0d0a65c 100644 --- a/src/H5Fprivate.h +++ b/src/H5Fprivate.h @@ -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); @@ -10,15 +10,15 @@ * * Purpose: Symbol table functions. The functions that * begin with `H5G_stab_' don't understand the - * directory hierarchy; they operate on a single + * naming system; they operate on a single * symbol table at a time. * * The functions that begin with `H5G_node_' operate * on the leaf nodes of a symbol table B-tree. They * should be defined in the H5Gnode.c file. * - * The remaining functions know about the directory - * hierarchy. + * The remaining functions know how to traverse the + * group directed graph * * Modifications: * @@ -53,6 +53,266 @@ static hbool_t interface_initialize_g = FALSE; /*------------------------------------------------------------------------- + * Function: H5Gnew + * + * Purpose: Creates a new group in FILE and gives it the specified + * NAME. Unless NAME begins with `/' it is relative to the + * current working group. + * + * The optional SIZE_HINT specifies how much file space to + * reserve to store the names that will appear in this + * group (an even number of characters, counting the null + * terminator, is allocated for each name). If a non-positive + * value is supplied for the SIZE_HINT then a default size is + * chosen. + * + * See also: H5Gset(), H5Gpush(), H5Gpop() + * + * Errors: + * ARGS BADTYPE Not a file atom. + * ARGS BADVALUE No name given. + * ATOM BADATOM Can't unatomize file. + * SYM CANTINIT Can't close handle. + * SYM CANTINIT Can't create group. + * + * Return: Success: SUCCEED + * + * Failure: FAIL + * + * Programmer: Robb Matzke + * Wednesday, September 24, 1997 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +herr_t +H5Gnew (hid_t file, const char *name, size_t size_hint) +{ + H5F_t *f=NULL; + H5G_entry_t *grp_handle=NULL; + + FUNC_ENTER (H5Gnew, NULL, FAIL); + + /* Check/fix arguments */ + if (!name || !*name) { + HRETURN_ERROR (H5E_ARGS, H5E_BADVALUE, FAIL);/*no name given*/ + } + if (H5_FILE!=H5Aatom_group (file)) { + HRETURN_ERROR (H5E_ARGS, H5E_BADTYPE, FAIL);/*not a file atom*/ + } + if (NULL==(f=H5Aatom_object (file))) { + HRETURN_ERROR (H5E_ATOM, H5E_BADATOM, FAIL);/*can't unatomize file*/ + } + + /* Create the group */ + if (NULL==(grp_handle=H5G_new (f, name, size_hint))) { + /*can't create group*/ + HRETURN_ERROR (H5E_SYM, H5E_CANTINIT, FAIL); + } + + /* Close the group handle */ + if (H5G_close (f, grp_handle)<0) { + HRETURN_ERROR (H5E_SYM, H5E_CANTINIT, FAIL);/*can't close handle*/ + } + + FUNC_LEAVE (SUCCEED); +} + + + +/*------------------------------------------------------------------------- + * Function: H5Gset + * + * Purpose: Sets the working group for file handle FILE to the + * specified NAME. Unless NAME begins with a `/' it is + * interpretted relative to the current working group. + * + * Each file handle maintains its own notion of the current + * working group. That is, if a single file is opened with + * multiple calls to H5Fopen(), which returns multiple file + * handles, then each handle's current working group can be + * set independently of the other file handles for that file. + * + * See also: H5Gpush(), H5Gpop() + * + * Errors: + * ARGS BADTYPE Not a file atom. + * ARGS BADVALUE No name given. + * ATOM BADATOM Can't unatomize file. + * SYM CANTINIT Can't change current working group. + * + * Return: Success: SUCCEED + * + * Failure: FAIL + * + * Programmer: Robb Matzke + * Wednesday, September 24, 1997 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +herr_t +H5Gset (hid_t file, const char *name) +{ + H5F_t *f=NULL; + + FUNC_ENTER (H5Gset, NULL, FAIL); + + /* Check/fix arguments */ + if (!name || !*name) { + HRETURN_ERROR (H5E_ARGS, H5E_BADVALUE, FAIL);/*no name given*/ + } + if (H5_FILE!=H5Aatom_group (file)) { + HRETURN_ERROR (H5E_ARGS, H5E_BADTYPE, FAIL);/*not a file atom*/ + } + if (NULL==(f=H5Aatom_object (file))) { + HRETURN_ERROR (H5E_ATOM, H5E_BADATOM, FAIL);/*can't unatomize file*/ + } + + if (H5G_set (f, name)<0) { + /* Can't change current working group */ + HRETURN_ERROR (H5E_SYM, H5E_CANTINIT, FAIL); + } + + FUNC_LEAVE (SUCCEED); +} + + + +/*------------------------------------------------------------------------- + * Function: H5Gpush + * + * Purpose: Similar to H5Gset() except the new working group is pushed + * on a stack. + * + * Each file handle maintains its own notion of the current + * working group. That is, if a single file is opened with + * multiple calls to H5Fopen(), which returns multiple file + * handles, then each handle's current working group can be + * set independently of the other file handles for that file. + * + * See also: H5Gset(), H5Gpop() + * + * Errors: + * ARGS BADTYPE Not a file atom. + * ARGS BADVALUE No name given. + * ATOM BADATOM Can't unatomize file. + * SYM CANTINIT Can't change current working group. + * + * Return: Success: SUCCEED + * + * Failure: FAIL + * + * Programmer: Robb Matzke + * Wednesday, September 24, 1997 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +herr_t +H5Gpush (hid_t file, const char *name) +{ + H5F_t *f=NULL; + + FUNC_ENTER (H5Gpush, NULL, FAIL); + + /* Check/fix arguments */ + if (!name || !*name) { + HRETURN_ERROR (H5E_ARGS, H5E_BADVALUE, FAIL);/*no name given*/ + } + if (H5_FILE!=H5Aatom_group (file)) { + HRETURN_ERROR (H5E_ARGS, H5E_BADTYPE, FAIL);/*not a file atom*/ + } + if (NULL==(f=H5Aatom_object (file))) { + HRETURN_ERROR (H5E_ATOM, H5E_BADATOM, FAIL);/*can't unatomize file*/ + } + + if (H5G_push (f, name)<0) { + /* Can't change current working group */ + HRETURN_ERROR (H5E_SYM, H5E_CANTINIT, FAIL); + } + + FUNC_LEAVE (SUCCEED); +} + + + +/*------------------------------------------------------------------------- + * Function: H5Gpop + * + * Purpose: Removes the top (latest) entry from the working group stack + * and sets the current working group to the previous value. + * + * Each file handle maintains its own notion of the current + * working group. That is, if a single file is opened with + * multiple calls to H5Fopen(), which returns multiple file + * handles, then each handle's current working group can be + * set independently of the other file handles for that file. + * + * See also: H5Gset(), H5Gpush() + * + * Errors: + * ARGS BADTYPE Not a file atom. + * ATOM BADATOM Can't unatomize file. + * SYM CANTINIT Stack is empty. + * + * Return: Success: SUCCEED + * + * Failure: FAIL. The final entry cannot be popped from + * the group stack (but it can be changed + * with H5Gset()). + * + * Programmer: Robb Matzke + * Wednesday, September 24, 1997 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +herr_t +H5Gpop (hid_t file) +{ + H5F_t *f=NULL; + + FUNC_ENTER (H5Gpop, NULL, FAIL); + + /* Check/fix arguments */ + if (H5_FILE!=H5Aatom_group (file)) { + HRETURN_ERROR (H5E_ARGS, H5E_BADTYPE, FAIL);/*not a file atom*/ + } + if (NULL==(f=H5Aatom_object (file))) { + HRETURN_ERROR (H5E_ATOM, H5E_BADATOM, FAIL);/*can't unatomize file*/ + } + + if (H5G_pop (f)<0) { + /* Stack is empty */ + HRETURN_ERROR (H5E_SYM, H5E_CANTINIT, FAIL); + } + + FUNC_LEAVE (SUCCEED); +} + + + + +/* + *------------------------------------------------------------------------- + *------------------------------------------------------------------------- + * N O A P I F U N C T I O N S B E Y O N D T H I S P O I N T + *------------------------------------------------------------------------- + *------------------------------------------------------------------------- + */ + + + + + + + +/*------------------------------------------------------------------------- * Function: H5G_component * * Purpose: Returns the pointer to the first component of the @@ -67,7 +327,7 @@ static hbool_t interface_initialize_g = FALSE; * Failure: Ptr to the null terminator of NAME. * * Programmer: Robb Matzke - * robb@maya.nuance.com + * matzke@llnl.gov * Aug 11 1997 * * Modifications: @@ -102,7 +362,7 @@ H5G_component (const char *name, size_t *size_p) * Failure: Ptr to the null terminator of NAME. * * Programmer: Robb Matzke - * robb@maya.nuance.com + * matzke@llnl.gov * Aug 11 1997 * * Modifications: @@ -122,7 +382,7 @@ H5G_basename (const char *name, size_t *size_p) while (s>name && '/'!=s[-1]) --s; /*skip past base name*/ /* - * If the input was the name of the root directory `/' (or + * If the input was the name of the root group `/' (or * equivalent) then return the null string. */ if ('/'==*s) { @@ -142,42 +402,43 @@ H5G_basename (const char *name, size_t *size_p) * Purpose: (Partially) translates a name to a symbol table entry. * * Given a name (absolute or relative) return the symbol table - * entry for that name and for the directory that contains the - * base name. These entries (DIR_ENT and BASE_ENT) are returned + * entry for that name and for the group that contains the + * base name. These entries (GRP_ENT and BASE_ENT) are returned * through memory passed into the function by the caller. Either * or both pointers may be null. Absolute names are looked up - * relative to the root directory of file F while relative - * names are traversed beginning at the CWD argument. + * relative to the root group of file F while relative + * names are traversed beginning at the CWG argument. * * Consecutive slash characters are treated like single * slash characters. Trailing slashes are ignored. The - * component `.' is recognized as the current directory - * during the traversal (initially CWD), but the component + * component `.' is recognized as the current group + * during the traversal (initially CWG), but the component * `..' is not internally recognized (it is recognized if * such a name appears in the symbol table). * * If the name cannot be fully resolved, then REST will * point to the part of NAME where the traversal failed * (REST will always point to a relative name) and this - * function will return null. DIR_ENT will be initialized with - * information about the directory (or other object) at which + * function will return null. GRP_ENT will be initialized with + * information about the group (or other object) at which * the traversal failed. However, if the name can be fully * resolved, then REST points to the null terminator of NAME. * * As a special case, if the NAME is the name `/' (or - * equivalent) then DIR_ENT is initialized to all zero + * equivalent) then GRP_ENT is initialized to all zero * and a pointer to the root symbol table entry is returned. * * As a special case, if the NAME is the string `/foo' (or * equivalent) and the root symbol table entry points to a - * non-directory object with a name message with the value - * `foo' then DIR_ENT is initialized to all zero and a pointer + * non-group object with a name message with the value + * `foo' then GRP_ENT is initialized to all zero and a pointer * to the root symbol table entry is returned. * * Errors: - * DIRECTORY COMPLEN Component is too long. - * DIRECTORY NOTFOUND Component not found. - * DIRECTORY NOTFOUND Root not found. + * SYM COMPLEN Component is too long. + * SYM NOTFOUND Component not found. + * SYM NOTFOUND No root group. + * SYM NOTFOUND Root not found. * * Return: Success: Pointer to a cached symbol table entry if the * name can be fully resolved. The pointer is @@ -185,11 +446,11 @@ H5G_basename (const char *name, size_t *size_p) * is called. * * Failure: Null if the name could not be fully resolved. - * REST and DIR_ENT are initialized (possibly to + * REST and GRP_ENT are initialized (possibly to * zero if the failure occurred soon enough). * * Programmer: Robb Matzke - * robb@maya.nuance.com + * matzke@llnl.gov * Aug 11 1997 * * Modifications: @@ -197,10 +458,10 @@ H5G_basename (const char *name, size_t *size_p) *------------------------------------------------------------------------- */ static H5G_entry_t * -H5G_namei (H5F_t *f, H5G_entry_t *cwd, const char *name, - const char **rest, H5G_entry_t *dir_ent) +H5G_namei (H5F_t *f, H5G_entry_t *cwg, const char *name, + const char **rest, H5G_entry_t *grp_ent) { - H5G_entry_t dir; /*entry for current directory */ + H5G_entry_t grp; /*entry for current group */ size_t nchars; /*component name length */ char comp[1024]; /*component name buffer */ hbool_t aside = FALSE; /*did we look at a name message?*/ @@ -208,7 +469,7 @@ H5G_namei (H5F_t *f, H5G_entry_t *cwd, const char *name, /* clear output args before FUNC_ENTER() in case it fails */ if (rest) *rest = name; - if (dir_ent) memset (dir_ent, 0, sizeof(H5G_entry_t)); + if (grp_ent) memset (grp_ent, 0, sizeof(H5G_entry_t)); FUNC_ENTER (H5G_namei, NULL, NULL); @@ -216,18 +477,19 @@ H5G_namei (H5F_t *f, H5G_entry_t *cwd, const char *name, assert (f); assert (f->shared->root_sym); assert (name && *name); - assert (cwd || '/'==*name); + assert (cwg || '/'==*name); /* starting point */ if ('/'==*name) { if (f->shared->root_sym->header<=0) { - HRETURN_ERROR (H5E_DIRECTORY, H5E_NOTFOUND, NULL); + /* No root group */ + HRETURN_ERROR (H5E_SYM, H5E_NOTFOUND, NULL); } ret_value = f->shared->root_sym; - dir = *(f->shared->root_sym); + grp = *(f->shared->root_sym); } else { - ret_value = cwd; - dir = *cwd; + ret_value = cwg; + grp = *cwg; } /* traverse the name */ @@ -241,7 +503,7 @@ H5G_namei (H5F_t *f, H5G_entry_t *cwd, const char *name, /* * Advance to the next component of the name. */ - dir = *ret_value; + grp = *ret_value; ret_value = NULL; if (rest) *rest = name; @@ -251,23 +513,23 @@ H5G_namei (H5F_t *f, H5G_entry_t *cwd, const char *name, */ if (nchars+1 > sizeof(comp)) { /* component is too long */ - if (dir_ent) *dir_ent = dir; - HRETURN_ERROR (H5E_DIRECTORY, H5E_COMPLEN, NULL); + if (grp_ent) *grp_ent = grp; + HRETURN_ERROR (H5E_SYM, H5E_COMPLEN, NULL); } HDmemcpy (comp, name, nchars); comp[nchars] = '\0'; - if (NULL==(ret_value=H5G_stab_find (f, NO_ADDR, &dir, comp))) { + if (NULL==(ret_value=H5G_stab_find (f, NO_ADDR, &grp, comp))) { /* * Component was not found in the current symbol table, possibly - * because DIR isn't a symbol table. If it is the root symbol then + * because GRP isn't a symbol table. If it is the root symbol then * see if it has the appropriate name field. The ASIDE variable * prevents us from saying `/foo/foo' where the root object has * the name `foo'. */ H5O_name_t mesg={0}; - if (!aside && dir.header==f->shared->root_sym->header && - H5O_read (f, dir.header, &dir, H5O_NAME, 0, &mesg) && + if (!aside && grp.header==f->shared->root_sym->header && + H5O_read (f, grp.header, &grp, H5O_NAME, 0, &mesg) && !HDstrcmp (mesg.s, comp)) { H5O_reset (H5O_NAME, &mesg); ret_value = f->shared->root_sym; @@ -275,8 +537,8 @@ H5G_namei (H5F_t *f, H5G_entry_t *cwd, const char *name, } else { /* component not found */ H5O_reset (H5O_NAME, &mesg); - if (dir_ent) *dir_ent = dir; - HRETURN_ERROR (H5E_DIRECTORY, H5E_NOTFOUND, NULL); + if (grp_ent) *grp_ent = grp; + HRETURN_ERROR (H5E_SYM, H5E_NOTFOUND, NULL); } } @@ -286,17 +548,17 @@ H5G_namei (H5F_t *f, H5G_entry_t *cwd, const char *name, /* output parameters */ if (rest) *rest = name; /*final null*/ - if (dir_ent) { + if (grp_ent) { if (ret_value->header == f->shared->root_sym->header) { - HDmemset (dir_ent, 0, sizeof(H5G_entry_t)); /*root has no parent*/ + HDmemset (grp_ent, 0, sizeof(H5G_entry_t)); /*root has no parent*/ } else { - *dir_ent = dir; + *grp_ent = grp; } } /* Perhaps the root object doesn't even exist! */ if (ret_value->header<=0) { - HRETURN_ERROR (H5E_DIRECTORY, H5E_NOTFOUND, NULL); /*root not found*/ + HRETURN_ERROR (H5E_SYM, H5E_NOTFOUND, NULL); /*root not found*/ } FUNC_LEAVE (ret_value); @@ -306,10 +568,10 @@ H5G_namei (H5F_t *f, H5G_entry_t *cwd, const char *name, /*------------------------------------------------------------------------- * Function: H5G_mkroot * - * Purpose: Creates the root directory if it doesn't exist; otherwise + * Purpose: Creates the root group if it doesn't exist; otherwise * nothing happens. If the root symbol table entry previously - * pointed to something other than a directory, then that object - * is made a member of the root directory and is given a name + * pointed to something other than a group, then that object + * is made a member of the root group and is given a name * corresponding to the object's name message (the name message * is removed). If the root object doesn't have a name message * then the name `Root Object' is used. @@ -317,19 +579,21 @@ H5G_namei (H5F_t *f, H5G_entry_t *cwd, const char *name, * Warning: This function has a few subtleties. Be warned! * * Errors: - * DIRECTORY CANTINIT Can't create root. - * DIRECTORY CANTINIT Can't insert old root object in - * new root directory. - * DIRECTORY EXISTS Root directory already exists. + * SYM CANTINIT Can't open root object. + * SYM CANTINIT Can't reinsert old root object. + * SYM CANTINIT Cant create root. + * SYM EXISTS Root group already exists. + * SYM LINK Bad link count on old root object. + * SYM LINK Cant create root. * * Return: Success: SUCCEED * * Failure: FAIL. This function returns -2 if the - * failure is because a root directory already + * failure is because a root group already * exists. * * Programmer: Robb Matzke - * robb@maya.nuance.com + * matzke@llnl.gov * Aug 11 1997 * * Modifications: @@ -356,20 +620,21 @@ H5G_mkroot (H5F_t *f, size_t size_hint) /* * If we already have a root object, then open it and get it's name. The - * root object had better not already be a directory. Once the old root + * root object had better not already be a group. Once the old root * object is opened and we have a HANDLE, set the dirty bit on the handle. * This causes the handle data to be written back into f->root_sym by * H5G_close() if something goes wrong before the old root object is - * re-inserted back into the directory hierarchy. We might leak file + * re-inserted back into the group directed graph. We might leak file * memory, but at least we don't loose the original root object. */ if (f->shared->root_sym->header>0) { if (H5O_read (f, NO_ADDR, f->shared->root_sym, H5O_STAB, 0, &stab)) { - /* root directory already exists */ - HGOTO_ERROR (H5E_DIRECTORY, H5E_EXISTS, -2); - } else if (NULL==(handle=H5G_shadow_open (f, NULL, f->shared->root_sym))) { + /* root group already exists */ + HGOTO_ERROR (H5E_SYM, H5E_EXISTS, -2); + } else if (NULL==(handle=H5G_shadow_open (f, NULL, + f->shared->root_sym))) { /* can't open root object */ - HGOTO_ERROR (H5E_DIRECTORY, H5E_CANTINIT, FAIL); + HGOTO_ERROR (H5E_SYM, H5E_CANTINIT, FAIL); } else if (NULL==H5O_read (f, NO_ADDR, handle, H5O_NAME, 0, &name)) { obj_name = "Root Object"; } else { @@ -379,15 +644,15 @@ H5G_mkroot (H5F_t *f, size_t size_hint) } /* - * Create the new root directory directly into the file descriptor. If + * Create the new root group directly into the file descriptor. If * something goes wrong at this step, closing the `handle' will rewrite * info back into f->root_sym because we set the dirty bit. */ if (H5G_stab_new (f, f->shared->root_sym, size_hint)<0) { - HGOTO_ERROR (H5E_DIRECTORY, H5E_CANTINIT, FAIL); /*cant create root*/ + HGOTO_ERROR (H5E_SYM, H5E_CANTINIT, FAIL); /*cant create root*/ } if (1!=H5O_link (f, f->shared->root_sym, 1)) { - HGOTO_ERROR (H5E_DIRECTORY, H5E_LINK, FAIL); + HGOTO_ERROR (H5E_SYM, H5E_LINK, FAIL); } /* @@ -397,11 +662,13 @@ H5G_mkroot (H5F_t *f, size_t size_hint) */ if (obj_name) { if (1!=H5O_link (f, handle, 0)) { - HGOTO_ERROR (H5E_DIRECTORY, H5E_LINK, FAIL); + /* Bad link count on old root object */ + HGOTO_ERROR (H5E_SYM, H5E_LINK, FAIL); } if (NULL==(ent_ptr=H5G_stab_insert (f, f->shared->root_sym, obj_name, handle))) { - HGOTO_ERROR (H5E_DIRECTORY, H5E_CANTINIT, FAIL); + /* Can't reinsert old root object */ + HGOTO_ERROR (H5E_SYM, H5E_CANTINIT, FAIL); } /* @@ -418,10 +685,10 @@ H5G_mkroot (H5F_t *f, size_t size_hint) done: /* * If the handle is closed before the H5G_stab_insert() call that - * reinserts the root object into the directory hierarchy, then + * reinserts the root object into the group directed graph, then * H5G_close() will reset f->root_sym to point to the old root symbol and - * the new root directory (if it was created) will be unlinked from the - * directory hierarchy (and memory leaked). + * the new root group (if it was created) will be unlinked from the + * group directed graph (and memory leaked). */ if (handle) H5G_close (f, handle); H5O_reset (H5O_NAME, &name); @@ -431,32 +698,33 @@ H5G_mkroot (H5F_t *f, size_t size_hint) /*------------------------------------------------------------------------- - * Function: H5G_mkdir + * Function: H5G_new * - * Purpose: Creates a new empty directory with the specified name, + * Purpose: Creates a new empty group with the specified name, * opening it as an object. The name is either an absolute name - * or is relative to the current working directory. + * or is relative to the current working group. * - * A root directory is created implicitly by this function + * A root group is created implicitly by this function * when necessary. Calling this function with the name "/" * (or any equivalent name) will result in an H5E_EXISTS * failure. * * Errors: - * DIRECTORY CANTINIT Can't create dir. - * DIRECTORY CANTINIT Can't insert. - * DIRECTORY CANTINIT Lookup failed. - * DIRECTORY COMPLEN Component is too long. - * DIRECTORY EXISTS Already exists. - * DIRECTORY NOTFOUND Missing component. - * - * Return: Success: A handle to the open directory. Please call + * SYM CANTINIT Can't create grp. + * SYM CANTINIT Can't create root group. + * SYM CANTINIT Can't insert. + * SYM CANTINIT Can't open. + * SYM COMPLEN Component is too long. + * SYM EXISTS Already exists. + * SYM NOTFOUND Missing component. + * + * Return: Success: A handle to the open group. Please call * H5G_close() when you're done with it. * * Failure: NULL * * Programmer: Robb Matzke - * robb@maya.nuance.com + * matzke@llnl.gov * Aug 11 1997 * * Modifications: @@ -464,42 +732,43 @@ H5G_mkroot (H5F_t *f, size_t size_hint) *------------------------------------------------------------------------- */ H5G_entry_t * -H5G_mkdir (H5F_t *f, const char *name, size_t size_hint) +H5G_new (H5F_t *f, const char *name, size_t size_hint) { const char *rest=NULL; /*the base name */ - H5G_entry_t *cwd=NULL; /*current working directory */ - H5G_entry_t dir_ent; /*directory containing new dir */ - H5G_entry_t ent; /*new directory entry */ - H5G_entry_t *ent_ptr=NULL; /*ptr to new directory entry */ + H5G_entry_t *cwg=NULL; /*current working group */ + H5G_entry_t grp_ent; /*group containing new group */ + H5G_entry_t ent; /*new group entry */ + H5G_entry_t *ent_ptr=NULL; /*ptr to new group entry */ H5G_entry_t *ret_value=NULL; /*handle return value */ char _comp[1024]; /*name component */ size_t nchars; /*number of characters in compon*/ herr_t status; /*function return status */ - FUNC_ENTER (H5G_mkdir, NULL, NULL); + FUNC_ENTER (H5G_new, NULL, NULL); /* check args */ assert (f); assert (name && *name); #ifndef LATER - /* Get current working directory */ + /* Get current working group */ H5G_shadow_sync (f->shared->root_sym); - cwd = f->shared->root_sym; + cwg = f->shared->root_sym; #endif - assert (cwd || '/'==*name); + assert (cwg || '/'==*name); /* - * Try to create the root directory. Ignore the error if this function - * fails because the root directory already exists. + * Try to create the root group. Ignore the error if this function + * fails because the root group already exists. */ if ((status=H5G_mkroot (f, H5G_SIZE_HINT))<0 && -2!=status) { - HRETURN_ERROR (H5E_DIRECTORY, H5E_CANTINIT, NULL); + /* Can't create root group */ + HRETURN_ERROR (H5E_SYM, H5E_CANTINIT, NULL); } H5ECLEAR; /* lookup name */ - if (H5G_namei (f, cwd, name, &rest, &dir_ent)) { - HRETURN_ERROR (H5E_DIRECTORY, H5E_EXISTS, NULL); /*already exists*/ + if (H5G_namei (f, cwg, name, &rest, &grp_ent)) { + HRETURN_ERROR (H5E_SYM, H5E_EXISTS, NULL); /*already exists*/ } H5ECLEAR; /*it's OK that we didn't find it*/ @@ -509,10 +778,10 @@ H5G_mkdir (H5F_t *f, const char *name, size_t size_hint) if (rest[nchars]) { if (H5G_component (rest+nchars, NULL)) { /* missing component */ - HRETURN_ERROR (H5E_DIRECTORY, H5E_NOTFOUND, NULL); + HRETURN_ERROR (H5E_SYM, H5E_NOTFOUND, NULL); } else if (nchars+1 > sizeof _comp) { /* component is too long */ - HRETURN_ERROR (H5E_DIRECTORY, H5E_COMPLEN, NULL); + HRETURN_ERROR (H5E_SYM, H5E_COMPLEN, NULL); } else { /* null terminate */ HDmemcpy (_comp, rest, nchars); @@ -521,19 +790,19 @@ H5G_mkdir (H5F_t *f, const char *name, size_t size_hint) } } - /* create directory */ + /* create group */ if (H5G_stab_new (f, &ent, size_hint)<0) { - HRETURN_ERROR (H5E_DIRECTORY, H5E_CANTINIT, NULL); /*can't create dir*/ + HRETURN_ERROR (H5E_SYM, H5E_CANTINIT, NULL); /*can't create grp*/ } /* insert child name into parent */ - if (NULL==(ent_ptr=H5G_stab_insert (f, &dir_ent, rest, &ent))) { - HRETURN_ERROR (H5E_DIRECTORY, H5E_CANTINIT, NULL); /*can't insert*/ + if (NULL==(ent_ptr=H5G_stab_insert (f, &grp_ent, rest, &ent))) { + HRETURN_ERROR (H5E_SYM, H5E_CANTINIT, NULL); /*can't insert*/ } - /* open the directory */ - if (NULL==(ret_value=H5G_shadow_open (f, &dir_ent, ent_ptr))) { - HRETURN_ERROR (H5E_DIRECTORY, H5E_CANTINIT, NULL); /*can't open*/ + /* open the group */ + if (NULL==(ret_value=H5G_shadow_open (f, &grp_ent, ent_ptr))) { + HRETURN_ERROR (H5E_SYM, H5E_CANTINIT, NULL); /*can't open*/ } FUNC_LEAVE (ret_value); @@ -542,9 +811,121 @@ H5G_mkdir (H5F_t *f, const char *name, size_t size_hint) /*------------------------------------------------------------------------- - * Function: H5G_pushd + * Function: H5G_set + * + * Purpose: Sets the current working group to be the specified name. + * This affects only the top item on the group stack for the + * specified file as accessed through this file handle. If the + * file is opened multiple times, then the current working group + * for this file handle is the only one that is changed. * - * Purpose: Pushes a new current working directory onto the stack. + * Errors: + * SYM CWG Can't open group. + * SYM CWG Couldn't close previous c.w.g. + * SYM CWG Not a group. + * + * Return: Success: SUCCEED + * + * Failure: FAIL + * + * Programmer: Robb Matzke + * Wednesday, September 24, 1997 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +herr_t +H5G_set (H5F_t *f, const char *name) +{ + H5G_entry_t *handle=NULL; + H5O_stab_t stab_mesg; + herr_t ret_value=FAIL; + + FUNC_ENTER (H5G_set, NULL, FAIL); + + if (NULL==(handle=H5G_open (f, name))) { + /* Can't open group */ + HGOTO_ERROR (H5E_SYM, H5E_CWG, FAIL); + } + if (NULL==H5O_read (f, NO_ADDR, handle, H5O_NAME, 0, &stab_mesg)) { + /* Not a group */ + HGOTO_ERROR (H5E_SYM, H5E_CWG, FAIL); + } + + /* + * If there is no stack then create one, otherwise close the current + * working group. + */ + if (!f->cwg_stack) { + f->cwg_stack = H5MM_xcalloc (1, sizeof(H5G_cwgstk_t)); + f->cwg_stack->handle = handle; + } else { + if (H5G_close (f, f->cwg_stack->handle)<0) { + /* Couldn't close previous c.w.g. */ + HGOTO_ERROR (H5E_SYM, H5E_CWG, FAIL); + } + f->cwg_stack->handle = handle; + } + ret_value = SUCCEED; + + done: + if (ret_value<0 && handle) { + H5G_close (f, handle); + } + + FUNC_LEAVE (ret_value); +} + + + +/*------------------------------------------------------------------------- + * Function: H5G_getcwg + * + * Purpose: Returns a handle for the current working group. If there + * is no current working group then a pointer to the root + * symbol is returned but that object is not opened (and it + * might not even be a group). + * + * Return: Success: Ptr to open group handle with exceptions + * noted above. + * + * Failure: NULL + * + * Programmer: Robb Matzke + * Wednesday, September 24, 1997 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static H5G_entry_t * +H5G_getcwg (H5F_t *f) +{ + H5G_entry_t *handle=NULL; + + FUNC_ENTER (H5G_getcwg, NULL, NULL); + + if (f->cwg_stack && f->cwg_stack->handle) { + handle = f->cwg_stack->handle; + } else { + H5G_shadow_sync (f->shared->root_sym); + handle = f->shared->root_sym; + } + + FUNC_LEAVE (handle); +} + + + +/*------------------------------------------------------------------------- + * Function: H5G_push + * + * Purpose: Pushes a new current working group onto the stack. + * + * Errors: + * SYM CWG Can't open group. + * SYM CWG Not a group. * * Return: Success: SUCCEED * @@ -558,31 +939,54 @@ H5G_mkdir (H5F_t *f, const char *name, size_t size_hint) *------------------------------------------------------------------------- */ herr_t -H5G_pushd (H5F_t *f, const char *name) +H5G_push (H5F_t *f, const char *name) { + H5G_entry_t *handle=NULL; + H5G_cwgstk_t *stack=NULL; + H5O_stab_t stab_mesg; + herr_t ret_value = FAIL; + FUNC_ENTER (H5G_pushd, NULL, FAIL); -#ifndef LATER + if (NULL==(handle=H5G_open (f, name))) { + /* Can't open group */ + HGOTO_ERROR (H5E_SYM, H5E_CWG, FAIL); + } + if (NULL==H5O_read (f, NO_ADDR, handle, H5O_NAME, 0, &stab_mesg)) { + /* Not a group */ + HGOTO_ERROR (H5E_SYM, H5E_CWG, FAIL); + } + /* - * Current working directories are not implemented yet. + * Push a new entry onto the stack. */ - if (strcmp (name, "/")) { - HRETURN_ERROR (H5E_INTERNAL, H5E_UNSUPPORTED, FAIL); + stack = H5MM_xcalloc (1, sizeof(H5G_cwgstk_t)); + stack->handle = handle; + stack->next = f->cwg_stack; + f->cwg_stack = stack; + ret_value = SUCCEED; + + done: + if (ret_value<0 && handle) { + H5G_close (f, handle); } -#endif - + FUNC_LEAVE (SUCCEED); } /*------------------------------------------------------------------------- - * Function: H5G_popd + * Function: H5G_pop * - * Purpose: Pops the top current working directory off the stack. + * Purpose: Pops the top current working group off the stack. + * + * Errors: + * SYM CWG Can't close current working group. + * SYM CWG Stack is empty. * * Return: Success: SUCCEED * - * Failure: FAIL + * Failure: FAIL if the stack is empty. * * Programmer: Robb Matzke * Friday, September 19, 1997 @@ -592,13 +996,24 @@ H5G_pushd (H5F_t *f, const char *name) *------------------------------------------------------------------------- */ herr_t -H5G_popd (H5F_t *f) +H5G_pop (H5F_t *f) { - FUNC_ENTER (H5G_popd, NULL, FAIL); + H5G_cwgstk_t *stack=NULL; + + FUNC_ENTER (H5G_pop, NULL, FAIL); -#ifndef LATER - /* CWD is not implemented yet. */ -#endif + if ((stack=f->cwg_stack)) { + if (H5G_close (f, stack->handle)<0) { + /* Can't close current working group */ + HRETURN_ERROR (H5E_SYM, H5E_CWG, FAIL); + } + f->cwg_stack = stack->next; + stack->handle = NULL; + H5MM_xfree (stack); + } else { + /* Stack is empty */ + HRETURN_ERROR (H5E_SYM, H5E_CWG, FAIL); + } FUNC_LEAVE (SUCCEED); } @@ -612,6 +1027,21 @@ H5G_popd (H5F_t *f) * object. The initial size of the object header can be * supplied with the OHDR_HINT argument. * + * Errors: + * SYM CANTINIT Bad link count. + * SYM CANTINIT Can't create header. + * SYM CANTINIT Can't create root group. + * SYM CANTINIT Can't insert. + * SYM CANTINIT Can't open object. + * SYM CANTINIT Cannot add/change name message. + * SYM CANTINIT Create the object header. + * SYM COMPLEN Component is too long. + * SYM EXISTS Already exists. + * SYM EXISTS Root exists. + * SYM LINK Bad link count. + * SYM LINK Link inc failure. + * SYM NOTFOUND Component not found. + * * Return: Success: A handle for the object. Be sure to * eventually close it. * @@ -629,9 +1059,9 @@ H5G_create (H5F_t *f, const char *name, size_t ohdr_hint) { H5G_entry_t ent; /*entry data for the new object */ H5G_entry_t *ent_ptr; /*ptr into symbol node for entry*/ - H5G_entry_t *cwd=NULL; /*ptr to CWD handle */ + H5G_entry_t *cwg=NULL; /*ptr to c.w.g. handle */ const char *rest = NULL; /*part of name not existing yet */ - H5G_entry_t dir; /*entry for dir to contain obj */ + H5G_entry_t grp; /*entry for group to contain obj*/ H5G_entry_t *ret_value=NULL; /*the object handle */ size_t nchars; /*number of characters in name */ char _comp[1024]; /*name component */ @@ -644,18 +1074,15 @@ H5G_create (H5F_t *f, const char *name, size_t ohdr_hint) HDmemset (&ent, 0, sizeof(H5G_entry_t)); /* - * Get the current working directory. + * Get the current working group. */ -#ifndef LATER - H5G_shadow_sync (f->shared->root_sym); - cwd = f->shared->root_sym; -#endif + cwg = H5G_getcwg (f); /* * Look up the name -- it shouldn't exist yet. */ - if (H5G_namei (f, cwd, name, &rest, &dir)) { - HRETURN_ERROR (H5E_DIRECTORY, H5E_EXISTS, NULL); /*already exists*/ + if (H5G_namei (f, cwg, name, &rest, &grp)) { + HRETURN_ERROR (H5E_SYM, H5E_EXISTS, NULL); /*already exists*/ } H5ECLEAR; /*it's OK that we didn't find it*/ rest = H5G_component (rest, &nchars); @@ -667,18 +1094,18 @@ H5G_create (H5F_t *f, const char *name, size_t ohdr_hint) * it already has as a message. */ if (f->shared->root_sym->header>0) { - HRETURN_ERROR (H5E_DIRECTORY, H5E_EXISTS, NULL); /*root exists*/ + HRETURN_ERROR (H5E_SYM, H5E_EXISTS, NULL); /*root exists*/ } if ((ent.header = H5O_new (f, 0, ohdr_hint))<0) { /* can't create header */ - HRETURN_ERROR (H5E_DIRECTORY, H5E_CANTINIT, NULL); + HRETURN_ERROR (H5E_SYM, H5E_CANTINIT, NULL); } if (1!=H5O_link (f, &ent, 1)) { - HRETURN_ERROR (H5E_DIRECTORY, H5E_LINK, NULL); /*bad link count*/ + HRETURN_ERROR (H5E_SYM, H5E_LINK, NULL); /*bad link count*/ } *(f->shared->root_sym) = ent; - if (NULL==(ret_value=H5G_shadow_open (f, &dir, f->shared->root_sym))) { - HRETURN_ERROR (H5E_DIRECTORY, H5E_CANTINIT, NULL); + if (NULL==(ret_value=H5G_shadow_open (f, &grp, f->shared->root_sym))) { + HRETURN_ERROR (H5E_SYM, H5E_CANTINIT, NULL); } HRETURN (ret_value); } @@ -690,10 +1117,10 @@ H5G_create (H5F_t *f, const char *name, size_t ohdr_hint) if (rest[nchars]) { if (H5G_component (rest+nchars, NULL)) { /* component not found */ - HRETURN_ERROR (H5E_DIRECTORY, H5E_NOTFOUND, NULL); + HRETURN_ERROR (H5E_SYM, H5E_NOTFOUND, NULL); } else if (nchars+1 > sizeof _comp) { /* component is too long */ - HRETURN_ERROR (H5E_DIRECTORY, H5E_COMPLEN, NULL); + HRETURN_ERROR (H5E_SYM, H5E_COMPLEN, NULL); } else { /* null terminate */ HDmemcpy (_comp, rest, nchars); @@ -706,7 +1133,7 @@ H5G_create (H5F_t *f, const char *name, size_t ohdr_hint) * Create the object header. */ if ((ent.header = H5O_new (f, 0, ohdr_hint))<0) { - HRETURN_ERROR (H5E_DIRECTORY, H5E_CANTINIT, NULL); + HRETURN_ERROR (H5E_SYM, H5E_CANTINIT, NULL); } @@ -721,28 +1148,29 @@ H5G_create (H5F_t *f, const char *name, size_t ohdr_hint) name_mesg.s = rest; if (H5O_modify (f, NO_ADDR, &ent, H5O_NAME, 0, &name_mesg)<0) { /* cannot add/change name message */ - HRETURN_ERROR (H5E_DIRECTORY, H5E_CANTINIT, NULL); + HRETURN_ERROR (H5E_SYM, H5E_CANTINIT, NULL); } if (1!=H5O_link (f, &ent, 1)) { - HRETURN_ERROR (H5E_DIRECTORY, H5E_LINK, NULL); /*bad link count*/ + HRETURN_ERROR (H5E_SYM, H5E_LINK, NULL); /*bad link count*/ } *(f->shared->root_sym) = ent; - if (NULL==(ret_value=H5G_shadow_open (f, &dir, f->shared->root_sym))) { - HRETURN_ERROR (H5E_DIRECTORY, H5E_CANTINIT, NULL); + if (NULL==(ret_value=H5G_shadow_open (f, &grp, f->shared->root_sym))) { + HRETURN_ERROR (H5E_SYM, H5E_CANTINIT, NULL); } HRETURN (ret_value); } else { /* - * Make sure the root directory exists. Ignore the failure if it's - * because the directory already exists. + * Make sure the root group exists. Ignore the failure if it's + * because the group already exists. */ - hbool_t update_dir = (dir.header==f->shared->root_sym->header); + hbool_t update_grp = (grp.header==f->shared->root_sym->header); herr_t status = H5G_mkroot (f, H5G_SIZE_HINT); if (status<0 && -2!=status) { - HRETURN_ERROR (H5E_DIRECTORY, H5E_CANTINIT, NULL); + /* Can't create root group */ + HRETURN_ERROR (H5E_SYM, H5E_CANTINIT, NULL); } H5ECLEAR; - if (update_dir) dir = *(f->shared->root_sym); + if (update_grp) grp = *(f->shared->root_sym); } /* @@ -750,13 +1178,13 @@ H5G_create (H5F_t *f, const char *name, size_t ohdr_hint) * entry into a symbol table. */ if (H5O_link (f, &ent, 1)<0) { - HRETURN_ERROR (H5E_DIRECTORY, H5E_LINK, NULL); /*link inc failure*/ + HRETURN_ERROR (H5E_SYM, H5E_LINK, NULL); /*link inc failure*/ } - if (NULL==(ent_ptr=H5G_stab_insert (f, &dir, rest, &ent))) { - HRETURN_ERROR (H5E_DIRECTORY, H5E_CANTINIT, NULL); /*can't insert*/ + if (NULL==(ent_ptr=H5G_stab_insert (f, &grp, rest, &ent))) { + HRETURN_ERROR (H5E_SYM, H5E_CANTINIT, NULL); /*can't insert*/ } - if (NULL==(ret_value=H5G_shadow_open (f, &dir, ent_ptr))) { - HRETURN_ERROR (H5E_DIRECTORY, H5E_CANTINIT, NULL); /*can't open object*/ + if (NULL==(ret_value=H5G_shadow_open (f, &grp, ent_ptr))) { + HRETURN_ERROR (H5E_SYM, H5E_CANTINIT, NULL); /*can't open object*/ } FUNC_LEAVE (ret_value); } @@ -776,6 +1204,11 @@ H5G_create (H5F_t *f, const char *name, size_t ohdr_hint) * structs. The structs that are returned should be * released by calling H5G_close(). * + * Errors: + * SYM BADVALUE Check args. + * SYM CANTOPENOBJ Can't open obj. + * SYM NOTFOUND Object not found. + * * Return: Success: Ptr to a handle for the object. * * Failure: NULL @@ -792,32 +1225,29 @@ H5G_open (H5F_t *f, const char *name) { H5G_entry_t *ent=NULL; H5G_entry_t *ret_value=NULL; - H5G_entry_t dir; - H5G_entry_t *cwd=NULL; + H5G_entry_t grp; + H5G_entry_t *cwg=NULL; FUNC_ENTER (H5G_open, NULL, NULL); /* check args */ assert (f); if (!name || !*name) { - HRETURN_ERROR (H5E_DIRECTORY, H5E_BADVALUE, NULL); + HRETURN_ERROR (H5E_SYM, H5E_BADVALUE, NULL); } - /* Get CWD */ -#ifndef LATER - H5G_shadow_sync (f->shared->root_sym); - cwd = f->shared->root_sym; -#endif - assert (cwd || '/'==*name); + /* Get CWG */ + cwg = H5G_getcwg (f); + assert (cwg || '/'==*name); if (f->shared->root_sym->header<=0) { - HRETURN_ERROR (H5E_DIRECTORY, H5E_NOTFOUND, NULL); /*object not found*/ + HRETURN_ERROR (H5E_SYM, H5E_NOTFOUND, NULL); /*object not found*/ } - if (NULL==(ent=H5G_namei (f, cwd, name, NULL, &dir))) { - HRETURN_ERROR (H5E_DIRECTORY, H5E_NOTFOUND, NULL); /*object not found*/ + if (NULL==(ent=H5G_namei (f, cwg, name, NULL, &grp))) { + HRETURN_ERROR (H5E_SYM, H5E_NOTFOUND, NULL); /*object not found*/ } - if (NULL==(ret_value=H5G_shadow_open (f, &dir, ent))) { - HRETURN_ERROR (H5E_DIRECTORY, H5E_CANTOPENOBJ, NULL); + if (NULL==(ret_value=H5G_shadow_open (f, &grp, ent))) { + HRETURN_ERROR (H5E_SYM, H5E_CANTOPENOBJ, NULL); /*can't open obj*/ } FUNC_LEAVE (ret_value); @@ -830,6 +1260,9 @@ H5G_open (H5F_t *f, const char *name) * * Purpose: Closes an object that was open for modification. * + * Errors: + * SYM CANTFLUSH Can't close object. + * * Return: Success: SUCCEED * * Failure: FAIL @@ -849,6 +1282,7 @@ H5G_close (H5F_t *f, H5G_entry_t *ent) assert (f); if (ent && H5G_shadow_close (f, ent)<0) { + /* Can't close object */ HRETURN_ERROR (H5E_SYM, H5E_CANTFLUSH, FAIL); } @@ -861,22 +1295,21 @@ H5G_close (H5F_t *f, H5G_entry_t *ent) * * Purpose: Finds an object with the specified NAME in file F. If * the name is relative then it is interpretted relative - * to CWD, a symbol table entry for a symbol table. On - * successful return, DIR_ENT (if non-null) will be - * initialized with the symbol table information for the - * directory in which the object appears (or all zero if - * the returned object is the root object) and ENT will - * be initialized with the symbol table entry for the - * object (ENT is optional when the caller is interested - * only in the existence of the object). + * to the current working group. On successful return, + * GRP_ENT (if non-null) will be initialized with the symbol + * table information for the group in which the object + * appears (or all zero if the returned object is the root + * object) and ENT will be initialized with the symbol table + * entry for the object (ENT is optional when the caller is + * interested only in the existence of the object). * * This function will fail if the root object is * requested and there is none. * * Errors: - * DIRECTORY NOTFOUND Object not found. + * SYM NOTFOUND Object not found. * - * Return: Success: SUCCEED with DIR_ENT and ENT initialized. ENT + * Return: Success: SUCCEED with GRP_ENT and ENT initialized. ENT * is intended for immediate read-only access. * If the object that ENT refers to is open * through the ENT entry (see H5G_open()) then @@ -888,7 +1321,7 @@ H5G_close (H5F_t *f, H5G_entry_t *ent) * Failure: FAIL * * Programmer: Robb Matzke - * robb@maya.nuance.com + * matzke@llnl.gov * Aug 12 1997 * * Modifications: @@ -896,23 +1329,25 @@ 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) +H5G_find (H5F_t *f, const char *name, H5G_entry_t *grp_ent, H5G_entry_t *ent) { H5G_entry_t *ent_p = NULL; + H5G_entry_t *cwg = NULL; + FUNC_ENTER (H5G_find, NULL, FAIL); /* check args */ assert (f); assert (name && *name); - assert (cwd || '/'==*name); + cwg = H5G_getcwg (f); + assert (cwg || '/'==*name); if (f->shared->root_sym->header<=0) { - HRETURN_ERROR (H5E_DIRECTORY, H5E_NOTFOUND, FAIL); /*object not found*/ + HRETURN_ERROR (H5E_SYM, H5E_NOTFOUND, FAIL); /*object not found*/ } - if (NULL==(ent_p=H5G_namei (f, cwd, name, NULL, dir_ent))) { - HRETURN_ERROR (H5E_DIRECTORY, H5E_NOTFOUND, FAIL); /*object not found*/ + if (NULL==(ent_p=H5G_namei (f, cwg, name, NULL, grp_ent))) { + HRETURN_ERROR (H5E_SYM, H5E_NOTFOUND, FAIL); /*object not found*/ } if (ent) *ent = *ent_p; diff --git a/src/H5Gent.c b/src/H5Gent.c index f9ca290..b5cddce 100644 --- a/src/H5Gent.c +++ b/src/H5Gent.c @@ -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: diff --git a/src/H5Gnode.c b/src/H5Gnode.c index 84dc0e5..58c924c 100644 --- a/src/H5Gnode.c +++ b/src/H5Gnode.c @@ -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) @@ -693,19 +699,11 @@ H5G_node_insert (H5F_t *f, haddr_t addr, intn *anchor, 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); } diff --git a/src/H5Gpkg.h b/src/H5Gpkg.h index e0d6f8d..9421541 100644 --- a/src/H5Gpkg.h +++ b/src/H5Gpkg.h @@ -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 */ @@ -78,6 +78,16 @@ typedef struct H5G_node_key_t { } 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. diff --git a/src/H5Gprivate.h b/src/H5Gprivate.h index 79666e7..4641d90 100644 --- a/src/H5Gprivate.h +++ b/src/H5Gprivate.h @@ -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); diff --git a/src/H5Gpublic.h b/src/H5Gpublic.h index 049c823..e546e6d 100644 --- a/src/H5Gpublic.h +++ b/src/H5Gpublic.h @@ -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 diff --git a/src/H5Gshad.c b/src/H5Gshad.c index 9bf80d8..875f880 100644 --- a/src/H5Gshad.c +++ b/src/H5Gshad.c @@ -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); diff --git a/src/H5Gstab.c b/src/H5Gstab.c index b600e90..7acaa13 100644 --- a/src/H5Gstab.c +++ b/src/H5Gstab.c @@ -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; @@ -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); } @@ -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); } diff --git a/src/H5Oistore.c b/src/H5Oistore.c new file mode 100644 index 0000000..1ed275e --- /dev/null +++ b/src/H5Oistore.c @@ -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); +} + diff --git a/src/H5Oname.c b/src/H5Oname.c index 7d76fa5..9d8aa09 100644 --- a/src/H5Oname.c +++ b/src/H5Oname.c @@ -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: diff --git a/src/H5Oprivate.h b/src/H5Oprivate.h index 94dd764..c4ad1cb 100644 --- a/src/H5Oprivate.h +++ b/src/H5Oprivate.h @@ -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. diff --git a/src/H5Osdtyp.c b/src/H5Osdtyp.c index 367af17..0800e30 100644 --- a/src/H5Osdtyp.c +++ b/src/H5Osdtyp.c @@ -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) { diff --git a/src/H5config.h.in b/src/H5config.h.in index 20da7a1..07a0615 100644 --- a/src/H5config.h.in +++ b/src/H5config.h.in @@ -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 diff --git a/src/H5private.h b/src/H5private.h index f13ff59..58db166 100644 --- a/src/H5private.h +++ b/src/H5private.h @@ -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) /*------------------------------------------------------------------------- diff --git a/src/Makefile.in b/src/Makefile.in index cebf3c1..8776376 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -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) diff --git a/test/Makefile.in b/test/Makefile.in index 8a7d4f0..d2cbe3a 100644 --- a/test/Makefile.in +++ b/test/Makefile.in @@ -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@ diff --git a/test/istore.c b/test/istore.c new file mode 100644 index 0000000..9f6fa1f --- /dev/null +++ b/test/istore.c @@ -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); +} diff --git a/test/tstab.c b/test/tstab.c index 652029f..d2f6de4 100644 --- a/test/tstab.c +++ b/test/tstab.c @@ -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; |