diff options
author | Quincey Koziol <koziol@hdfgroup.org> | 1997-07-30 21:17:56 (GMT) |
---|---|---|
committer | Quincey Koziol <koziol@hdfgroup.org> | 1997-07-30 21:17:56 (GMT) |
commit | 03997b1f368f935ab4b3a9a878fd3587cbc74862 (patch) | |
tree | 193909bb46d7310f8ea8d31308cddc8850530220 | |
parent | ad9255a57faca8454d0a5f2f955001eed32833ea (diff) | |
download | hdf5-03997b1f368f935ab4b3a9a878fd3587cbc74862.zip hdf5-03997b1f368f935ab4b3a9a878fd3587cbc74862.tar.gz hdf5-03997b1f368f935ab4b3a9a878fd3587cbc74862.tar.bz2 |
[svn-r2] Oops...
-rw-r--r-- | Makefile | 117 | ||||
-rw-r--r-- | src/H5.c | 275 | ||||
-rw-r--r-- | src/H5A.c | 789 | ||||
-rw-r--r-- | src/H5AC.c | 315 | ||||
-rw-r--r-- | src/H5ACprivate.h | 71 | ||||
-rw-r--r-- | src/H5ACproto.h | 29 | ||||
-rw-r--r-- | src/H5Aprivate.h | 90 | ||||
-rw-r--r-- | src/H5Aproto.h | 204 | ||||
-rw-r--r-- | src/H5B.c | 1177 | ||||
-rw-r--r-- | src/H5Bprivate.h | 85 | ||||
-rw-r--r-- | src/H5Bproto.h | 29 | ||||
-rw-r--r-- | src/H5C.c | 506 | ||||
-rw-r--r-- | src/H5Cprivate.h | 25 | ||||
-rw-r--r-- | src/H5Cproto.h | 41 | ||||
-rw-r--r-- | src/H5E.c | 394 | ||||
-rw-r--r-- | src/H5Eprivate.h | 131 | ||||
-rw-r--r-- | src/H5Eproto.h | 126 | ||||
-rw-r--r-- | src/H5F.c | 852 | ||||
-rw-r--r-- | src/H5Fprivate.h | 101 | ||||
-rw-r--r-- | src/H5Fproto.h | 43 | ||||
-rw-r--r-- | src/H5G.c | 196 | ||||
-rw-r--r-- | src/H5Gnode.c | 661 | ||||
-rw-r--r-- | src/H5Gprivate.h | 125 | ||||
-rw-r--r-- | src/H5Gproto.h | 29 | ||||
-rw-r--r-- | src/H5H.c | 653 | ||||
-rw-r--r-- | src/H5Hprivate.h | 36 | ||||
-rw-r--r-- | src/H5Hproto.h | 29 | ||||
-rw-r--r-- | src/H5M.c | 257 | ||||
-rw-r--r-- | src/H5MF.c | 88 | ||||
-rw-r--r-- | src/H5MFprivate.h | 28 | ||||
-rw-r--r-- | src/H5MFproto.h | 29 | ||||
-rw-r--r-- | src/H5MM.c | 175 | ||||
-rw-r--r-- | src/H5MMprivate.h | 32 | ||||
-rw-r--r-- | src/H5MMproto.h | 29 | ||||
-rw-r--r-- | src/H5Mprivate.h | 86 | ||||
-rw-r--r-- | src/H5Mproto.h | 37 | ||||
-rw-r--r-- | src/H5P.c | 216 | ||||
-rw-r--r-- | src/H5Pprivate.h | 30 | ||||
-rw-r--r-- | src/H5Pproto.h | 39 | ||||
-rw-r--r-- | src/H5T.c | 662 | ||||
-rw-r--r-- | src/H5Tprivate.h | 50 | ||||
-rw-r--r-- | src/H5Tproto.h | 57 | ||||
-rw-r--r-- | src/H5private.h | 30 | ||||
-rw-r--r-- | src/H5proto.h | 35 | ||||
-rw-r--r-- | src/Makefile | 92 | ||||
-rw-r--r-- | src/h5oplat.h | 555 | ||||
-rw-r--r-- | src/hdf5.h | 60 | ||||
-rw-r--r-- | src/hdf5fort.h | 75 | ||||
-rw-r--r-- | src/hdf5gen.h | 49 | ||||
-rw-r--r-- | src/hdf5glob.h | 58 | ||||
-rw-r--r-- | src/hdf5lims.h | 60 | ||||
-rw-r--r-- | src/hdf5meta.h | 145 | ||||
-rw-r--r-- | src/hdf5pabl.h | 32 | ||||
-rw-r--r-- | src/hdf5plat.h | 750 | ||||
-rw-r--r-- | src/hdf5port.h | 202 | ||||
-rw-r--r-- | src/hdf5type.h | 70 | ||||
-rw-r--r-- | test/Makefile | 50 | ||||
-rw-r--r-- | test/testhdf5.c | 302 | ||||
-rw-r--r-- | test/testhdf5.h | 115 | ||||
-rw-r--r-- | test/tfile.c | 288 | ||||
-rw-r--r-- | test/theap.c | 87 | ||||
-rw-r--r-- | test/tmeta.c | 120 |
62 files changed, 12119 insertions, 0 deletions
diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..c081fc9 --- /dev/null +++ b/Makefile @@ -0,0 +1,117 @@ +# ################################################################## +# +# +# This is the top level Makefile to build HDF5 on Unix based +# platforms +# + +# Define your sh shell +#SHELL=/bin/sh + +# Define your machine type +#MACHINE=UNIX386 + +# Define your C compiler and flags +CC= gcc +#CFLAGS= -ansi -Wall -pedantic -O -c +CFLAGS= -ansi -Wall -pedantic -g -c + +# Define your FORTRAN compiler +FC= f77 +FFLAGS= + +# Location where the HDF include files are to be installed +HDFINC= `pwd`/src + +# Location where the HDF library is to be installed +HDFLIB= `pwd`/src + +# Location to put HDF utility executables +HDFBIN= `pwd`/bin + +# Name of library archiver and flags to send +AR= ar +ARFLAGS= ru + +# Name of achive randomizer (use 'touch' if non-existant) +RANLIB= ranlib + +# Name of remove utility +RM= /bin/rm +RMFLAGS= -f + +# ################################################################## +# +# This is the top level Makefile to build HDF5 on Unix based +# platforms +# + +# +# +# Flags to recursively send +# + +HDF_FLAGS = \ + CC="$(CC)" \ + CFLAGS="$(CFLAGS)" \ + FC="$(FC)" \ + FFLAGS="$(FFLAGS)" \ + RANLIB="$(RANLIB)" \ + AR="$(AR)" \ + ARFLAGS="$(ARFLAGS)" \ + RM="$(RM)" \ + RMFLAGS="$(RMFLAGS)" \ + MACHINE="$(MACHINE)" \ + HDFLIB="$(HDFLIB)" \ + HDFINC="$(HDFINC)" \ + HDFBIN="$(HDFBIN)" + +# +# +# General rules +# +all: + @$(MAKE) $(MFLAGS) $(HDF_FLAGS) TARG=$@ \ + SUBDIRS="src test" subd message + +rebuild: + @$(MAKE) $(MFLAGS) $(HDF_FLAGS) TARG=$@ \ + SUBDIRS="src test" subd message + +libhdf5: + @$(MAKE) $(MFLAGS) $(HDF_FLAGS) TARG=all \ + SUBDIRS="src" subd + +tests: + @$(MAKE) $(MFLAGS) $(HDF_FLAGS) TARG=test \ + SUBDIRS="src test" subd + +debug: + @$(MAKE) $(MFLAGS) $(HDF_FLAGS) TARG=debug \ + SUBDIRS="src test" subd message + +clean: + @$(MAKE) $(MFLAGS) $(HDF_FLAGS) TARG=$@ \ + SUBDIRS="src test" subd + $(RM) $(RMFLAGS) core *.log + +distclean: + @$(MAKE) $(MFLAGS) $(HDF_FLAGS) TARG=$@ \ + SUBDIRS="src test" subd + $(RM) $(RMFLAGS) core *.log + $(RM) -rf bin lib include + +subd: + @for dir in $(SUBDIRS); do \ + (cd $$dir; echo Making \`$(TARG)\' in `pwd`; \ + $(MAKE) $(MFLAGS) $(HDF_FLAGS) $(TARG)); \ + done + +message: + @echo "" + @echo "***********************************************************" + @echo " HDF5 library successfully created." + @echo "" + @echo "***********************************************************" + @echo "" + diff --git a/src/H5.c b/src/H5.c new file mode 100644 index 0000000..cf77b61 --- /dev/null +++ b/src/H5.c @@ -0,0 +1,275 @@ +/**************************************************************************** +* NCSA HDF * +* Software Development Group * +* National Center for Supercomputing Applications * +* University of Illinois at Urbana-Champaign * +* 605 E. Springfield, Champaign IL 61820 * +* * +* For conditions of distribution and use, see the accompanying * +* hdf/COPYING file. * +* * +****************************************************************************/ + +#ifdef RCSID +static char RcsId[] = "@(#)$Revision$"; +#endif + +/* $Id$ */ + +/*LINTLIBRARY */ +/*+ + FILE + hdf5.c + HDF library support routines + + EXPORTED ROUTINES + H5dont_atexit -- Indicate that an 'atexit' routine is _not_ to be installed + H5version -- Check the version of the library + + LIBRARY-SCOPED ROUTINES + H5_init_library -- initialize the HDF5 library + H5_term_library -- shut-down the HDF5 library + H5_init_thread -- initialize thread-specific information + + LOCAL ROUTINES + H5_init_interface -- initialize the H5 interface + + */ + +#define HDF5_MASTER +#include "hdf5.h" +#undef HDF5_MASTER + +/* private headers */ +#include "H5ACprivate.h" /*cache */ +#include "H5Bprivate.h" /*B-link trees */ +#include "H5private.h" /* Generic info */ + +/*--------------------- Locally scoped variables -----------------------------*/ + +/* Whether we've installed the library termination function yet for this interface */ +static intn interface_initialize = FALSE; + +/*------------------_-- Local function prototypes ----------------------------*/ +static herr_t H5_init_interface(void); + +/*-------------------------------------------------------------------------- +NAME + H5_init_library -- Initialize library-global information +USAGE + herr_t H5_init_library() + +RETURNS + SUCCEED/FAIL +DESCRIPTION + Initializes any library-global data or routines. + +--------------------------------------------------------------------------*/ +herr_t H5_init_library(void) +{ + CONSTR(FUNC, "H5_init_library"); /* For HERROR */ + herr_t ret_value = SUCCEED; + + /* Don't use "FUNC_ENTER" macro, to avoid potential infinite recursion */ + PABLO_TRACE_ON(H5_mask, ID_H5_init_library); + + /* Don't call this routine again... */ + library_initialize = TRUE; + + /* Install atexit() library cleanup routine */ + if(install_atexit==TRUE) + if (HDatexit(&H5_term_library) != 0) + HGOTO_ERROR(H5E_FUNC, H5E_CANTINIT, FAIL); + +done: + if(ret_value == FAIL) + { /* Error condition cleanup */ + + } /* end if */ + + FUNC_LEAVE(H5_mask, ID_H5_init_library,ret_value); +} /* H5_init_library */ + +/*-------------------------------------------------------------------------- + NAME + H5_term_library + PURPOSE + Terminate various static buffers and shutdown the library. + USAGE + void HPend() + RETURNS + none + DESCRIPTION + Walk through the shutdown routines for the various interfaces and + terminate them all. + GLOBAL VARIABLES + COMMENTS, BUGS, ASSUMPTIONS + Should only ever be called by the "atexit" function, or real power-users. + EXAMPLES + REVISION LOG +--------------------------------------------------------------------------*/ +void H5_term_library(void) +{ +#ifdef LATER + CONSTR(FUNC, "H5_term_library"); /* for HERROR */ +#endif /* LATER */ + +} /* end H5_term_library() */ + +/*-------------------------------------------------------------------------- +NAME + H5_init_thread -- Initialize thread-specific information +USAGE + void H5_init_thread() + +RETURNS + SUCCEED/FAIL +DESCRIPTION + Initializes any thread-specific data or routines. + +--------------------------------------------------------------------------*/ +herr_t H5_init_thread(void) +{ +#ifdef LATER + CONSTR(FUNC, "H5_init_thread"); /* For HERROR */ +#endif /* LATER */ + herr_t ret_value = SUCCEED; + + /* Don't use "FUNC_ENTER" macro, to avoid potential infinite recursion */ + PABLO_TRACE_ON(H5_mask, ID_H5_init_thread); + + /* Don't call this routine again... */ + thread_initialize = TRUE; + + + /* Create/initialize this thread's error stack */ + if((thrderrid=H5Enew_err_stack(16))==FAIL) + ret_value=FAIL; + + FUNC_LEAVE(H5_mask, ID_H5_init_thread, ret_value); +} /* H5_init_thread */ + +/*-------------------------------------------------------------------------- +NAME + H5_init_interface -- Initialize interface-specific information +USAGE + herr_t H5_init_interface() + +RETURNS + SUCCEED/FAIL +DESCRIPTION + Initializes any interface-specific data or routines. + +--------------------------------------------------------------------------*/ +static herr_t H5_init_interface(void) +{ +#ifdef LATER + CONSTR(FUNC, "H5_init_interface"); /* For HERROR */ +#endif /* LATER */ + herr_t ret_value = SUCCEED; + + /* Don't use "FUNC_ENTER" macro, to avoid potential infinite recursion */ + PABLO_TRACE_ON(H5_mask, ID_H5_init_interface); + + /* Don't call this routine again... */ + interface_initialize = TRUE; + + FUNC_LEAVE(H5_mask, ID_H5_init_interface, ret_value); +} /* H5_init_interface */ + +/*-------------------------------------------------------------------------- + NAME + H5dont_atexit + PURPOSE + Indicates to the library that an 'atexit()' routine is _not_ to be installed + USAGE + herr_t H5dont_atexit(void) + RETURNS + Returns SUCCEED/FAIL + DESCRIPTION + This routine indicates to the library that an 'atexit()' cleanip routine + should not be installed. The major (only?) purpose for this is in + situations where the library is dynamically linked into an application and + is un-linked from the application before 'exit()' gets callled. In those + situations, a routine installed with 'atexit()' would jump to a routine + which was no longer in memory, causing errors. + In order to be effective, this routine _must_ be called before any other + HDF function calls, and must be called each time the library is loaded/ + linked into the application. (the first time and after it's been un-loaded) + GLOBAL VARIABLES + COMMENTS, BUGS, ASSUMPTIONS + If this routine is used, certain memory buffers will not be de-allocated, + although in theory a user could call HPend on their own... + EXAMPLES + REVISION LOG +--------------------------------------------------------------------------*/ +herr_t H5dont_atexit(void) +{ +#ifdef LATER + CONSTR(FUNC, "H5dont_atexit"); /* for HERROR */ +#endif /* LATER */ + intn ret_value = SUCCEED; + + /* Don't use "FUNC_ENTER" macro, we are trying to avoid certain initialization code */ + PABLO_TRACE_ON(H5_mask, ID_H5dont_atexit); + + if(install_atexit == TRUE) + install_atexit=FALSE; + +#ifdef LATER +done: + if(ret_value == FAIL) + { /* Error condition cleanup */ + + } /* end if */ +#endif /* LATER */ + + /* Normal function cleanup */ + + FUNC_LEAVE(H5_mask, ID_H5dont_atexit,ret_value); +} /* end H5dont_atexit() */ + +/*-------------------------------------------------------------------------- +NAME + H5version -- Checks the version of the library +USAGE + herr_t H5version(majnum, minnum, relnum, patnum) + uintn *majnum; OUT: The major revision number of the HDF5 library + uintn *minnum; OUT: The minor revision number of the HDF5 library + uintn *relnum; OUT: The release revision number of the HDF5 library + uintn *patnum; OUT: The patch revision number of the HDF5 library + +RETURNS + SUCCEED/FAIL +DESCRIPTION + Checks the version numbers of the library. + +--------------------------------------------------------------------------*/ +herr_t H5version(uintn *majnum, uintn *minnum, uintn *relnum, uintn *patnum) +{ + CONSTR(FUNC, "H5version"); /* For HERROR */ + herr_t ret_value = SUCCEED; + + FUNC_ENTER(H5_mask, ID_H5version, H5_init_interface,FAIL); + + /* Clear errors and check args and all the boring stuff. */ + H5ECLEAR; + if (majnum==NULL || minnum==NULL || relnum==NULL || patnum==NULL) + HGOTO_ERROR(H5E_ARGS, H5E_BADRANGE, FAIL); + + /* Set the version information */ + *majnum=HDF5_MAJOR_VERSION; + *minnum=HDF5_MINOR_VERSION; + *relnum=HDF5_RELEASE_VERSION; + *patnum=HDF5_PATCH_VERSION; + +done: + if(ret_value == FAIL) + { /* Error condition cleanup */ + + } /* end if */ + + /* Normal function cleanup */ + + FUNC_LEAVE(H5_mask, ID_H5version, ret_value); +} /* H5version */ + diff --git a/src/H5A.c b/src/H5A.c new file mode 100644 index 0000000..3733bf8 --- /dev/null +++ b/src/H5A.c @@ -0,0 +1,789 @@ +/**************************************************************************** + * NCSA HDF * + * Software Development Group * + * National Center for Supercomputing Applications * + * University of Illinois at Urbana-Champaign * + * 605 E. Springfield, Champaign IL 61820 * + * * + * For conditions of distribution and use, see the accompanying * + * hdf/COPYING file. * + * * + ****************************************************************************/ + +#ifdef RCSID +static char RcsId[] = "@(#)$Revision$"; +#endif + +/* $Id$ */ + +/* +FILE + atom.c - Internal storage routines for handling "atoms" + +REMARKS + Atoms are just ID's which allow objects (void *'s currently) to be + bundled into "groups" for more general storage. + +DESIGN + The groups are stored in an array of pointers to store each group in an + element. Each "atomic group" node contains a link to a hash table to + manage the atoms in each group. The allowed "atomic groups" are stored + in an enum (called group_t) in atom.h. + +BUGS/LIMITATIONS + Can't interate over the atoms in a group. + +LOCAL ROUTINES + H5A_find_atom - Returns a pointer to an atom_info_t from a atom ID + H5A_get_atom_node - Gets an atom node (uses the atom free list) + H5A_release_atom_node - Releases an atom node (uses the atom free list) +EXPORTED ROUTINES + Atom Functions: + H5Aregister_atom - Register an object in a group and get an atom for it + H5Aatom_object - Get the object for an atom + H5Aatom_group - Get the group for an atom + H5Aremove_atom - Remove an atom from a group + H5Asearch_atom - Search a group for a particular object + H5Ais_reserved - Check whether an atom is a reserved atom in a group + Atom Group Functions: + H5Ainit_group - Initialize a group to store atoms in + H5Adestroy_group - Destroy an atomic group + Atom Group Cleanup: + H5Ashutdown - Terminate various static buffers. + +AUTHOR + Quincey Koziol + +MODIFICATION HISTORY + 1/3/96 - Starting writing specs & coding prototype + 1/7/96 - Finished coding prototype + 6/10/97 - Moved into HDF5 library +*/ + +#define HDF5_ATOM_MASTER +#include "hdf5.h" +#include "H5Aprivate.h" + + +/* Private function prototypes */ +static atom_info_t *H5A_find_atom(hatom_t atm); + +static atom_info_t *H5A_get_atom_node(void); + +static void H5A_release_atom_node(atom_info_t *atm); + +/****************************************************************************** + NAME + H5Ainit_group - Initialize an atomic group + + DESCRIPTION + Creates a global atomic group to store atoms in. If the group has already + been initialized, this routine just increments the count of # of + initializations and returns without trying to change the size of the hash + table. A specific number of group entries may be reserved to enable + "constant" values to be handed out which are valid atoms in the group, but + which do not map to any data structures and are not allocated dynamicly + later. + + RETURNS + Returns SUCCEED if successful and FAIL otherwise + +*******************************************************************************/ +intn H5Ainit_group(group_t grp, /* IN: Group to initialize */ + intn hash_size, /* IN: Minimum hash table size to use for group */ + uintn reserved /* IN: Number of hash table entries to reserve */ +) +{ +#ifdef LATER + CONSTR(FUNC, "H5Ainit_group"); /* for HERROR */ +#endif /* LATER */ + atom_group_t *grp_ptr=NULL; /* ptr to the atomic group */ + intn ret_value=SUCCEED; + + PABLO_TRACE_ON(H5A_mask, ID_H5Ainit_group); + + if((grp<=BADGROUP || grp>=MAXGROUP) && hash_size>0) + HGOTO_DONE(FAIL); + +#ifdef HASH_SIZE_POWER_2 + /* If anyone knows a faster test for a power of two, please change this silly code -QAK */ + if(!(hash_size==2 || hash_size==4 || hash_size==8 || hash_size==16 + || hash_size==32 || hash_size==64 || hash_size==128 || hash_size==256 + || hash_size==512 || hash_size==1024 || hash_size==2048 + || hash_size==4096 || hash_size==8192 || hash_size==16374 + || hash_size==32768 || hash_size==65536 || hash_size==131072 + || hash_size==262144 || hash_size==524288 || hash_size==1048576 + || hash_size==2097152 || hash_size==4194304 || hash_size==8388608 + || hash_size==16777216 || hash_size==33554432 || hash_size==67108864 + || hash_size==134217728 || hash_size==268435456)) + HGOTO_DONE(FAIL); +#endif /* HASH_SIZE_POWER_2 */ + + if(atom_group_list[grp]==NULL) + { /* Allocate the group information */ + grp_ptr=(atom_group_t *)HDcalloc(1,sizeof(atom_group_t)); + if(grp_ptr==NULL) + HGOTO_DONE(FAIL); + atom_group_list[grp]=grp_ptr; + } /* end if */ + else /* Get the pointer to the existing group */ + grp_ptr=atom_group_list[grp]; + + if(grp_ptr->count==0) + { /* Initialize the atom group structure */ + grp_ptr->hash_size=hash_size; + grp_ptr->reserved=reserved; + grp_ptr->wrapped=0; + grp_ptr->atoms=0; + grp_ptr->nextid=0; + if((grp_ptr->atom_list=(atom_info_t **)HDcalloc(hash_size,sizeof(atom_info_t *)))==NULL) + HGOTO_DONE(FAIL); + } /* end if */ + + /* Increment the count of the times this group has been initialized */ + grp_ptr->count++; + +#ifdef QAK +printf("%s: group ID=%d, count=%d, current # of active atoms=%d\n",FUNC,grp,grp_ptr->count,grp_ptr->atoms); +#endif /* QAK */ +done: + if(ret_value == FAIL) + { /* Error condition cleanup */ + if(grp_ptr!=NULL) + { + if(grp_ptr->atom_list!=NULL) + HDfree(grp_ptr->atom_list); + HDfree(grp_ptr); + } /* end if */ + } /* end if */ + + /* Normal function cleanup */ + FUNC_LEAVE(H5A_mask, ID_H5Ainit_group, ret_value); +} /* end H5Ainit_group() */ + +/****************************************************************************** + NAME + H5Adestroy_group - Destroy an atomic group + + DESCRIPTION + Destroys an atomic group which atoms are stored in. If the group still + has atoms which are registered, this routine fails. If there have been + multiple initializations of the group, this routine just decrements the + count of initializations and does not check the atoms out-standing. + + RETURNS + Returns SUCCEED if successful and FAIL otherwise + +*******************************************************************************/ +intn H5Adestroy_group(group_t grp /* IN: Group to destroy */ +) +{ +#ifdef LATER + CONSTR(FUNC, "H5Adestroy_group"); /* for HERROR */ +#endif /* LATER */ + atom_group_t *grp_ptr=NULL; /* ptr to the atomic group */ + intn ret_value=SUCCEED; + + PABLO_TRACE_ON(H5A_mask, ID_H5Adestroy_group); + + if(grp<=BADGROUP || grp>=MAXGROUP) + HGOTO_DONE(FAIL); + + grp_ptr=atom_group_list[grp]; + if(grp_ptr==NULL || grp_ptr->count<=0) + HGOTO_DONE(FAIL); + +#ifdef QAK +printf("%s: group ID=%d, count=%d, current # of active atoms=%d\n",FUNC,grp,grp_ptr->count,grp_ptr->atoms); +#endif /* QAK */ + /* Decrement the number of users of the atomic group */ + if((--(grp_ptr->count))==0) + { +#ifdef ATOMS_ARE_CACHED + { + uintn i; + + for(i=0; i<ATOM_CACHE_SIZE; i++) + if(ATOM_TO_GROUP(atom_id_cache[i])==grp) + { + atom_id_cache[i]=(-1); + atom_obj_cache[i]=NULL; + } /* end if */ + } /* end block */ +#endif /* ATOMS_ARE_CACHED */ + HDfree(grp_ptr->atom_list); + } /* end if */ + +done: + if(ret_value == FAIL) + { /* Error condition cleanup */ + + } /* end if */ + + /* Normal function cleanup */ + FUNC_LEAVE(H5A_mask, ID_H5Adestroy_group, ret_value); +} /* end H5Adestroy_group() */ + +/****************************************************************************** + NAME + H5Aregister_atom - Register an object in a group and get an atom for it. + + DESCRIPTION + Registers an object in a group and returns an atom for it. This routine + does _not_ check for unique-ness of the objects, if you register an object + twice, you will get two different atoms for it. This routine does make + certain that each atom in a group is unique. Atoms are created by getting + a unique number for the group the atom is in and incorporating the group + into the atom which is returned to the user. + + RETURNS + Returns atom if successful and FAIL otherwise + +*******************************************************************************/ +hatom_t H5Aregister_atom(group_t grp, /* IN: Group to register the object in */ + const VOIDP object /* IN: Object to attach to atom */ +) +{ +#ifdef LATER + CONSTR(FUNC, "H5Aregister_atom"); /* for HERROR */ +#endif /* LATER */ + atom_group_t *grp_ptr=NULL; /* ptr to the atomic group */ + atom_info_t *atm_ptr=NULL; /* ptr to the new atom */ + hatom_t atm_id; /* new atom ID */ + uintn hash_loc; /* new item's hash table location */ + hatom_t ret_value=SUCCEED; + + PABLO_TRACE_ON(H5A_mask, ID_H5Aregister_atom); + + if(grp<=BADGROUP || grp>=MAXGROUP) + HGOTO_DONE(FAIL); + + grp_ptr=atom_group_list[grp]; + if(grp_ptr==NULL || grp_ptr->count<=0) + HGOTO_DONE(FAIL); + + if((atm_ptr=H5A_get_atom_node())==NULL) + HGOTO_DONE(FAIL); + + /* Create the atom & it's ID */ + atm_id=MAKE_ATOM(grp,grp_ptr->nextid); + atm_ptr->id=atm_id; + atm_ptr->obj_ptr=object; + atm_ptr->next=NULL; + + /* hash bucket already full, prepend to front of chain */ + hash_loc=grp_ptr->nextid%(uintn)grp_ptr->hash_size; + if(grp_ptr->atom_list[hash_loc]!=NULL) + atm_ptr->next=grp_ptr->atom_list[hash_loc]; + + /* Insert into the group */ + grp_ptr->atom_list[hash_loc]=atm_ptr; + grp_ptr->atoms++; + grp_ptr->nextid++; + + /* + * This next section of code checks for the 'nextid' getting too large and + * wrapping around, thus necessitating checking for duplicate atoms being + * handed out. + */ + if(grp_ptr->nextid>(uintn)ATOM_MASK || grp_ptr->wrapped!=0) + { + if(grp_ptr->wrapped==0) + { + grp_ptr->wrapped=1; /* set the "wrapped around" flag if it isn't already */ + grp_ptr->nextid=grp_ptr->reserved; /* re-start the ID counter */ + } /* end if */ + do { + hatom_t next_atom=MAKE_ATOM(grp,grp_ptr->nextid); /* new atom to check for */ + atom_info_t *curr_atm; /* ptr to the current atom */ + + curr_atm=grp_ptr->atom_list[(uintn)ATOM_TO_LOC(grp_ptr->nextid,grp_ptr->hash_size)]; + if(curr_atm==NULL) /* Ha! this is not likely... */ + break; + + while(curr_atm!=NULL) + { + if(curr_atm->id==next_atom) + break; + curr_atm=curr_atm->next; + } /* end while */ + if(curr_atm==NULL) /* must not have found a match */ + break; + grp_ptr->nextid++; + } while(grp_ptr->nextid<=(uintn)ATOM_MASK); + if(grp_ptr->nextid>(uintn)ATOM_MASK) /* All the atoms are gone! */ + HGOTO_DONE(FAIL); + } /* end if */ + + ret_value=atm_id; + +done: + if(ret_value == FAIL) + { /* Error condition cleanup */ + + } /* end if */ + + /* Normal function cleanup */ + FUNC_LEAVE(H5A_mask, ID_H5Aregister_atom, ret_value); +} /* end H5Aregister_atom() */ + +/****************************************************************************** + NAME + H5Aatom_object - Returns to the object ptr for the atom + + DESCRIPTION + Retrieves the object ptr which is associated with the atom. + + RETURNS + Returns object ptr if successful and NULL otherwise + +*******************************************************************************/ +VOIDP H5Aatom_object(hatom_t atm /* IN: Atom to retrieve object for */ +) +{ +#ifdef LATER + CONSTR(FUNC, "H5Aatom_object"); /* for HERROR */ +#endif /* LATER */ +#ifdef ATOMS_ARE_CACHED + uintn i; /* local counter */ +#endif /* ATOMS_ARE_CACHED */ + atom_info_t *atm_ptr=NULL; /* ptr to the new atom */ + VOIDP ret_value=NULL; + + PABLO_TRACE_ON(H5A_mask, ID_H5Aatom_object); + +#ifdef ATOMS_ARE_CACHED + /* Look for the atom in the cache first */ + for(i=0; i<ATOM_CACHE_SIZE; i++) + if(atom_id_cache[i]==atm) + { + ret_value=atom_obj_cache[i]; + if(i>0) + { /* Implement a simple "move forward" caching scheme */ + hatom_t t_atom=atom_id_cache[i-1]; + VOIDP t_obj=atom_obj_cache[i-1]; + + atom_id_cache[i-1]=atom_id_cache[i]; + atom_obj_cache[i-1]=atom_obj_cache[i]; + atom_id_cache[i]=t_atom; + atom_obj_cache[i]=t_obj; + } /* end if */ + HGOTO_DONE(ret_value); + } /* end if */ +#endif /* ATOMS_ARE_CACHED */ + + /* General lookup of the atom */ + if((atm_ptr=H5A_find_atom(atm))==NULL) + HGOTO_DONE(NULL); + + /* Check if we've found the correct atom */ + if(atm_ptr!=NULL) + ret_value=atm_ptr->obj_ptr; + +done: + if(ret_value == NULL) + { /* Error condition cleanup */ + + } /* end if */ + + /* Normal function cleanup */ + FUNC_LEAVE(H5A_mask, ID_H5Aatom_object, ret_value); +} /* end H5Aatom_object() */ + +/****************************************************************************** + NAME + H5Aatom_group - Returns to the group for the atom + + DESCRIPTION + Retrieves the group which is associated with the atom. + + RETURNS + Returns group if successful and BADGROUP otherwise + +*******************************************************************************/ +group_t H5Aatom_group(hatom_t atm /* IN: Atom to retrieve group for */ +) +{ +#ifdef LATER + CONSTR(FUNC, "H5Aatom_group"); /* for HERROR */ +#endif /* LATER */ + group_t ret_value=BADGROUP; + + PABLO_TRACE_ON(H5A_mask, ID_H5Aatom_group); + + ret_value=ATOM_TO_GROUP(atm); + if(ret_value<=BADGROUP || ret_value>=MAXGROUP) + HGOTO_DONE(BADGROUP); + +done: + if(ret_value == BADGROUP) + { /* Error condition cleanup */ + + } /* end if */ + + /* Normal function cleanup */ + FUNC_LEAVE(H5A_mask, ID_H5Aatom_group, ret_value); +} /* end H5Aatom_group() */ + +/****************************************************************************** + NAME + H5Aremove_atom - Removes an atom from a group + + DESCRIPTION + Removes an atom from a group. + + RETURNS + Returns atom's object if successful and NULL otherwise + +*******************************************************************************/ +VOIDP H5Aremove_atom(hatom_t atm /* IN: Atom to remove */ +) +{ +#ifdef LATER + CONSTR(FUNC, "H5Aremove_atom"); /* for HERROR */ +#endif /* LATER */ + atom_group_t *grp_ptr=NULL; /* ptr to the atomic group */ + atom_info_t *curr_atm, /* ptr to the current atom */ + *last_atm; /* ptr to the last atom */ + group_t grp; /* atom's atomic group */ + uintn hash_loc; /* atom's hash table location */ +#ifdef ATOMS_ARE_CACHED + uintn i; /* local counting variable */ +#endif /* ATOMS_ARE_CACHED */ + VOIDP ret_value=NULL; + + PABLO_TRACE_ON(H5A_mask, ID_H5Aremove_atom); + + grp=ATOM_TO_GROUP(atm); + if(grp<=BADGROUP || grp>=MAXGROUP) + HGOTO_DONE(NULL); + + grp_ptr=atom_group_list[grp]; + if(grp_ptr==NULL || grp_ptr->count<=0) + HGOTO_DONE(NULL); + + /* Get the location in which the atom is located */ + hash_loc=(uintn)ATOM_TO_LOC(atm,grp_ptr->hash_size); + curr_atm=grp_ptr->atom_list[hash_loc]; + if(curr_atm==NULL) + HGOTO_DONE(NULL); + + last_atm=NULL; + while(curr_atm!=NULL) + { + if(curr_atm->id==atm) + break; + last_atm=curr_atm; + curr_atm=curr_atm->next; + } /* end while */ + + if(curr_atm!=NULL) + { + if(last_atm==NULL) /* atom is the first the chain */ + grp_ptr->atom_list[hash_loc]=curr_atm->next; + else + last_atm->next=curr_atm->next; + ret_value=curr_atm->obj_ptr; + H5A_release_atom_node(curr_atm); + } /* end if */ + else /* couldn't find the atom in the proper place */ + HGOTO_DONE(NULL); + +#ifdef ATOMS_ARE_CACHED + /* Delete object from cache */ + for(i=0; i<ATOM_CACHE_SIZE; i++) + if(atom_id_cache[i]==atm) + { + atom_id_cache[i]=(-1); + atom_obj_cache[i]=NULL; + break; /* we assume there is only one instance in the cache */ + } /* end if */ +#endif /* ATOMS_ARE_CACHED */ + + /* Decrement the number of atoms in the group */ + (grp_ptr->atoms)--; + +done: + if(ret_value == NULL) + { /* Error condition cleanup */ + + } /* end if */ + + /* Normal function cleanup */ + FUNC_LEAVE(H5A_mask, ID_H5Aremove_atom, ret_value); +} /* end H5Aremove_atom() */ + +/****************************************************************************** + NAME + H5Asearch_atom - Search for an object in a group and get it's pointer. + + DESCRIPTION + Searchs for an object in a group and returns the pointer to it. + This routine calls the function pointer passed in for each object in the + group until it finds a match. Currently there is no way to resume a + search. + + RETURNS + Returns pointer an atom's object if successful and NULL otherwise + +*******************************************************************************/ +VOIDP H5Asearch_atom(group_t grp, /* IN: Group to search for the object in */ + H5Asearch_func_t func, /* IN: Ptr to the comparison function */ + const VOIDP key /* IN: pointer to key to compare against */ +) +{ +#ifdef LATER + CONSTR(FUNC, "H5Asearch_atom"); /* for HERROR */ +#endif /* LATER */ + atom_group_t *grp_ptr=NULL; /* ptr to the atomic group */ + atom_info_t *atm_ptr=NULL; /* ptr to the new atom */ + intn i; /* local counting variable */ + VOIDP ret_value=NULL; + + PABLO_TRACE_ON(H5A_mask, ID_H5Asearch_atom); + + if(grp<=BADGROUP || grp>=MAXGROUP) + HGOTO_DONE(NULL); + + grp_ptr=atom_group_list[grp]; + if(grp_ptr==NULL || grp_ptr->count<=0) + HGOTO_DONE(NULL); + + /* Start at the beginning of the array */ + for(i=0; i<grp_ptr->hash_size; i++) + { + atm_ptr=grp_ptr->atom_list[i]; + while(atm_ptr!=NULL) + { + if((*func)(atm_ptr->obj_ptr,key)) + HGOTO_DONE(atm_ptr->obj_ptr); /* found the item we are looking for */ + atm_ptr=atm_ptr->next; + } /* end while */ + } /* end for */ + +done: + if(ret_value == NULL) + { /* Error condition cleanup */ + + } /* end if */ + + /* Normal function cleanup */ + FUNC_LEAVE(H5A_mask, ID_H5Asearch_atom, ret_value); +} /* end H5Asearch_atom() */ + +/****************************************************************************** + NAME + H5Ais_reserved - Check whether an atom is a reserved atom in a group + + DESCRIPTION + Determines the group an atom belongs to and checks if the atom is a + reserved atom in the group. + + RETURNS + Returns BTRUE/BFALSE/BFAIL + +*******************************************************************************/ +intn H5Ais_reserved(hatom_t atm /* IN: Group to search for the object in */ +) +{ +#ifdef LATER + CONSTR(FUNC, "H5Ais_reserved"); /* for HERROR */ +#endif /* LATER */ + atom_group_t *grp_ptr=NULL; /* ptr to the atomic group */ + group_t grp; /* atom's atomic group */ + hbool_t ret_value=BFAIL; + + PABLO_TRACE_ON(H5A_mask, ID_H5Ais_reserved); + + grp=ATOM_TO_GROUP(atm); + if(grp<=BADGROUP || grp>=MAXGROUP) + HGOTO_DONE(BFAIL); + + grp_ptr=atom_group_list[grp]; + if(grp_ptr==NULL) + HGOTO_DONE(BFAIL); + + /* Get the location in which the atom is located */ + if((atm&ATOM_MASK)<grp_ptr->reserved) + ret_value=BTRUE; + else + ret_value=BFALSE; + +done: + if(ret_value == BFAIL) + { /* Error condition cleanup */ + + } /* end if */ + + /* Normal function cleanup */ + FUNC_LEAVE(H5A_mask, ID_H5Ais_reserved, ret_value); +} /* end H5Ais_reserved() */ + +/****************************************************************************** + NAME + H5A_find_atom - Finds a atom in a group + + DESCRIPTION + Retrieves the atom ptr which is associated with the atom. + + RETURNS + Returns atom ptr if successful and NULL otherwise + +*******************************************************************************/ +static atom_info_t *H5A_find_atom(hatom_t atm /* IN: Atom to retrieve atom for */ +) +{ +#ifdef LATER + CONSTR(FUNC, "H5A_find_atom"); /* for HERROR */ +#endif /* LATER */ + atom_group_t *grp_ptr=NULL; /* ptr to the atomic group */ + atom_info_t *atm_ptr=NULL; /* ptr to the new atom */ + group_t grp; /* atom's atomic group */ + uintn hash_loc; /* atom's hash table location */ + atom_info_t *ret_value=NULL; + + + grp=ATOM_TO_GROUP(atm); + if(grp<=BADGROUP || grp>=MAXGROUP) + HGOTO_DONE(NULL); + + grp_ptr=atom_group_list[grp]; + if(grp_ptr==NULL || grp_ptr->count<=0) + HGOTO_DONE(NULL); + + /* Get the location in which the atom is located */ + hash_loc=(uintn)ATOM_TO_LOC(atm,grp_ptr->hash_size); + atm_ptr=grp_ptr->atom_list[hash_loc]; + if(atm_ptr==NULL) + HGOTO_DONE(NULL); + + while(atm_ptr!=NULL) + { + if(atm_ptr->id==atm) + break; + atm_ptr=atm_ptr->next; + } /* end while */ + ret_value=atm_ptr; + +#ifdef ATOMS_ARE_CACHED + atom_id_cache[ATOM_CACHE_SIZE-1]=atm; + atom_obj_cache[ATOM_CACHE_SIZE-1]=atm_ptr->obj_ptr; +#endif /* ATOMS_ARE_CACHED */ + +done: + if(ret_value == NULL) + { /* Error condition cleanup */ + + } /* end if */ + + /* Normal function cleanup */ + + return ret_value; +} /* end H5A_find_atom() */ + +/****************************************************************************** + NAME + H5A_get_atom_node - Gets an atom node + + DESCRIPTION + Either gets an atom node from the free list (if there is one available) + or allocate a node. + + RETURNS + Returns atom ptr if successful and NULL otherwise + +*******************************************************************************/ +static atom_info_t *H5A_get_atom_node(void) +{ +#ifdef LATER + CONSTR(FUNC, "H5A_get_atom_node"); /* for HERROR */ +#endif /* LATER */ + atom_info_t *ret_value=NULL; + + if(atom_free_list!=NULL) + { + ret_value=atom_free_list; + atom_free_list=atom_free_list->next; + } /* end if */ + else + { + if((ret_value=(atom_info_t *)HDmalloc(sizeof(atom_info_t)))==NULL) + HGOTO_DONE(NULL); + } /* end else */ + +done: + if(ret_value == NULL) + { /* Error condition cleanup */ + + } /* end if */ + + /* Normal function cleanup */ + + return ret_value; +} /* end H5A_get_atom_node() */ + +/****************************************************************************** + NAME + H5A_release_atom_node - Releases an atom node + + DESCRIPTION + Puts an atom node into the free list + + RETURNS + No return value + +*******************************************************************************/ +static void H5A_release_atom_node(atom_info_t *atm) +{ +#ifdef LATER + CONSTR(FUNC, "H5A_release_atom_node"); /* for HERROR */ +#endif /* LATER */ + + /* Insert the atom at the beginning of the free list */ + atm->next=atom_free_list; + atom_free_list=atm; +} /* end H5A_release_atom_node() */ + +/*-------------------------------------------------------------------------- + NAME + H5Ashutdown + PURPOSE + Terminate various static buffers. + USAGE + intn H5Ashutdown() + RETURNS + Returns SUCCEED/FAIL + DESCRIPTION + Free various buffers allocated in the H5A routines. + GLOBAL VARIABLES + COMMENTS, BUGS, ASSUMPTIONS + Should only ever be called by the "atexit" function HDFend + EXAMPLES + REVISION LOG +--------------------------------------------------------------------------*/ +intn +H5Ashutdown(void) +{ + atom_info_t *curr; + intn i; + + /* Release the free-list if it exists */ + if(atom_free_list!=NULL) + { + while(atom_free_list!=NULL) + { + curr=atom_free_list; + atom_free_list=atom_free_list->next; + HDfree(curr); + } /* end while */ + } /* end if */ + + for(i=0; i<(intn)MAXGROUP; i++) + if(atom_group_list[i]!=NULL) + { + HDfree(atom_group_list[i]); + atom_group_list[i]=NULL; + } /* end if */ + return (SUCCEED); +} /* end H5Ashutdown() */ + diff --git a/src/H5AC.c b/src/H5AC.c new file mode 100644 index 0000000..a0123b1 --- /dev/null +++ b/src/H5AC.c @@ -0,0 +1,315 @@ +/*------------------------------------------------------------------------- + * Copyright (C) 1997 National Center for Supercomputing Applications. + * All rights reserved. + * + *------------------------------------------------------------------------- + * + * Created: hdf5cache.c + * Jul 9 1997 + * Robb Matzke <matzke@llnl.gov> + * + * Purpose: Functions in this file implement a cache for + * things which exist on disk. All "things" associated + * with a particular HDF file share the same cache; each + * HDF file has it's own cache. + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +#include <assert.h> +#include "hdf5.h" + +#include "H5ACprivate.h" + +#define HASH(addr) ((unsigned)(addr) % H5AC_NSLOTS) + + +/*------------------------------------------------------------------------- + * Function: H5AC_new + * + * Purpose: Initialize the cache just after a file is opened. + * + * Return: Success: 0 + * + * Failure: -1 + * + * Programmer: Robb Matzke + * robb@maya.nuance.com + * Jul 9 1997 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +herr_t +H5AC_new (hdf5_file_t *f) +{ + f->cache = HDcalloc (H5AC_NSLOTS, sizeof (H5AC_cache_t)); + return 0; +} + + +/*------------------------------------------------------------------------- + * Function: H5AC_dest + * + * Purpose: Flushes all data to disk and destroys the cache. + * + * Return: Success: 0 + * + * Failure: -1 + * + * Programmer: Robb Matzke + * robb@maya.nuance.com + * Jul 9 1997 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +herr_t +H5AC_dest (hdf5_file_t *f) +{ + if (H5AC_flush (f, NULL, 0, TRUE)<0) return -1; + HDfree (f->cache); + return 0; +} + + +/*------------------------------------------------------------------------- + * Function: H5AC_find + * + * 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. + * + * Return: Success: Pointer to the object. The pointer is + * valid until some other cache function + * is called. + * + * Failure: NULL + * + * Programmer: Robb Matzke + * robb@maya.nuance.com + * Jul 9 1997 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +void * +H5AC_find (hdf5_file_t *f, const H5AC_class_t *type, off_t addr, + const void *udata) +{ + unsigned idx = HASH(addr); + herr_t status; + void *thing = NULL; + herr_t (*flush)(hdf5_file_t*,hbool_t,off_t,void*)=NULL; + + assert (type); + assert (type->load); + assert (type->flush); + + /* + * Return right away if the item is in the cache. + */ + if (f->cache[idx].type==type && f->cache[idx].addr==addr) { + return f->cache[idx].thing; + } + + /* + * 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))) { + return NULL; + } + + /* + * Free the previous cache entry if there is one. + */ + if (f->cache[idx].type) { + flush = f->cache[idx].type->flush; + status = (flush)(f, TRUE, f->cache[idx].addr, f->cache[idx].thing); + if (status<0) { + /* + * The old thing could not be removed from the stack. + * Release the new thing and fail. + */ + status = (type->flush)(f, TRUE, addr, thing); + assert (status>=0); + return NULL; + } + } + + /* + * Make the cache point to the new thing. + */ + f->cache[idx].type = type; + f->cache[idx].addr = addr; + f->cache[idx].thing = thing; + + return thing; +} + + +/*------------------------------------------------------------------------- + * Function: H5AC_flush + * + * Purpose: Flushes (and destroys if DESTROY is non-zero) the specified + * entry from the cache. If the entry type is CACHE_FREE then + * all types of entries are flushed. If the ADDR is zero then + * all entries of the specified type are flushed. + * + * Return: Success: 0 + * + * Failure: -1 + * + * Programmer: Robb Matzke + * robb@maya.nuance.com + * Jul 9 1997 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +herr_t +H5AC_flush (hdf5_file_t *f, const H5AC_class_t *type, off_t addr, + hbool_t destroy) +{ + uintn i = HASH(addr); + herr_t status; + herr_t (*flush)(hdf5_file_t*,hbool_t,off_t,void*)=NULL; + + if (!type || 0==addr) { + /* + * Look at all cache entries. + */ + for (i=0; i<H5AC_NSLOTS; i++) { + if (NULL==f->cache[i].type) continue; + if ((!type || type==f->cache[i].type) && + (0==addr || addr==f->cache[i].addr)) { + flush = f->cache[i].type->flush; + status = (flush)(f, destroy, f->cache[i].addr, + f->cache[i].thing); + if (status<0) return -1; + if (destroy) f->cache[i].type = NULL; + } + } + + } else if (f->cache[i].type==type && f->cache[i].addr==addr) { + /* + * Flush just this entry. + */ + flush = f->cache[i].type->flush; + status = (flush) (f, destroy, f->cache[i].addr, f->cache[i].thing); + if (status<0) return -1; + if (destroy) f->cache[i].type = NULL; + + } + return 0; +} + + +/*------------------------------------------------------------------------- + * Function: H5AC_set + * + * Purpose: Adds the specified thing to the cache. The thing need not + * exist on disk yet, but it must have an address and disk + * space reserved. + * + * Return: Success: 0 + * + * Failure: -1 + * + * Programmer: Robb Matzke + * robb@maya.nuance.com + * Jul 9 1997 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +herr_t +H5AC_set (hdf5_file_t *f, const H5AC_class_t *type, off_t addr, void *thing) +{ + herr_t status; + uintn idx = HASH (addr); + herr_t (*flush)(hdf5_file_t*,hbool_t,off_t,void*)=NULL; + + assert (type); + assert (type->flush); + + if (f->cache[idx].type) { + flush = f->cache[idx].type->flush; + status = (flush)(f, TRUE, f->cache[idx].addr, f->cache[idx].thing); + if (status<0) return -1; + } + + f->cache[idx].type = type; + f->cache[idx].addr = addr; + f->cache[idx].thing = thing; + return 0; +} + + +/*------------------------------------------------------------------------- + * Function: H5AC_rename + * + * Purpose: Use this function to notify the cache that an object's + * file address changed. + * + * Return: Success: 0 + * + * Failure: -1 + * + * Programmer: Robb Matzke + * robb@maya.nuance.com + * Jul 9 1997 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +herr_t +H5AC_rename (hdf5_file_t *f, const H5AC_class_t *type, + off_t old_addr, off_t new_addr) +{ + uintn old_idx = HASH (old_addr); + uintn new_idx = HASH (new_addr); + herr_t (*flush)(hdf5_file_t*, hbool_t, off_t, void*); + herr_t status; + + assert (type); + + if (f->cache[old_idx].type!=type || f->cache[old_idx].addr!=old_addr) { + return 0; /*item not in cache*/ + } + + if (old_idx==new_idx) { + f->cache[old_idx].addr = new_addr; + return 0; + } + + /* + * Free the item from the destination cache line. + */ + if (f->cache[new_idx].type) { + flush = f->cache[new_idx].type->flush; + status = (flush)(f, TRUE, f->cache[new_idx].addr, + f->cache[new_idx].thing); + if (status<0) return -1; + } + + /* + * Move the source to the destination (it might not be cached) + */ + f->cache[new_idx].type = f->cache[old_idx].type; + f->cache[new_idx].addr = new_addr; + f->cache[new_idx].thing = f->cache[old_idx].thing; + f->cache[old_idx].type = NULL; + + return 0; +} + diff --git a/src/H5ACprivate.h b/src/H5ACprivate.h new file mode 100644 index 0000000..5dce2cd --- /dev/null +++ b/src/H5ACprivate.h @@ -0,0 +1,71 @@ +/*------------------------------------------------------------------------- + * Copyright (C) 1997 National Center for Supercomputing Applications. + * All rights reserved. + * + *------------------------------------------------------------------------- + * + * Created: H5ACprivate.h + * Jul 9 1997 + * Robb Matzke <robb@maya.nuance.com> + * + * Purpose: Constants and typedefs available to the rest of the + * library. + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +#ifndef _H5ACprivate_H +#define _H5ACprivate_H + +#include "H5ACproto.h" /*public prototypes */ +#include "H5Fprivate.h" /*for private hdf5_file_t definition */ + +/* + * Class methods pertaining to caching. Each type of cached object will + * have a constant variable with permanent life-span that describes how + * to cache the object. That variable will be of type H5AC_class_t and + * have the following required fields... + * + * LOAD: Loads an object from disk to memory. The function + * should allocate some data structure and return it. + * + * FLUSH: Writes some data structure back to disk. It would be + * wise for the data structure to include dirty flags to + * indicate whether it really needs to be written. This + * function is also responsible for freeing memory allocated + * by the LOAD method if the DEST argument is non-zero. + */ +typedef struct H5AC_class_t { + void *(*load)(hdf5_file_t*, off_t addr, const void *udata); + herr_t (*flush)(hdf5_file_t*, hbool_t dest, off_t addr, void *thing); +} H5AC_class_t; + +/* + * A cache has a certain number of entries. Objects are mapped into a + * cache entry by hashing the object's file address. Each file has its + * own cache, an array of slots. + */ +#define H5AC_NSLOTS 1033 /*prime number tend to work best */ + +typedef struct H5AC_cache_t { + const H5AC_class_t *type; /*type of object stored here */ + off_t addr; /*file address for object */ + void *thing; /*the thing which is cached */ +} H5AC_cache_t; + +/* + * Library prototypes. + */ +herr_t H5AC_dest (hdf5_file_t *f); +void *H5AC_find (hdf5_file_t *f, const H5AC_class_t *type, off_t addr, + const void *udata); +herr_t H5AC_flush (hdf5_file_t *f, const H5AC_class_t *type, off_t addr, + hbool_t destroy); +herr_t H5AC_new (hdf5_file_t *f); +herr_t H5AC_rename (hdf5_file_t *f, const H5AC_class_t *type, + off_t old, off_t new); +herr_t H5AC_set (hdf5_file_t *f, const H5AC_class_t *type, off_t addr, + void *thing); + +#endif /* !_H5ACprivate_H */ diff --git a/src/H5ACproto.h b/src/H5ACproto.h new file mode 100644 index 0000000..25218a9 --- /dev/null +++ b/src/H5ACproto.h @@ -0,0 +1,29 @@ +/*------------------------------------------------------------------------- + * Copyright (C) 1997 National Center for Supercomputing Applications. + * All rights reserved. + * + *------------------------------------------------------------------------- + * + * Created: H5ACproto.h + * Jul 10 1997 + * Robb Matzke <robb@maya.nuance.com> + * + * Purpose: Function prototypes for the H5AC package. + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +#ifndef _H5ACproto_H +#define _H5ACproto_H + +#if defined c_plusplus || defined __cplusplus +extern "C" +{ +#endif + +#if defined c_plusplus || defined __cplusplus +} +#endif + +#endif diff --git a/src/H5Aprivate.h b/src/H5Aprivate.h new file mode 100644 index 0000000..1a2db6f --- /dev/null +++ b/src/H5Aprivate.h @@ -0,0 +1,90 @@ +/**************************************************************************** + * NCSA HDF * + * Software Development Group * + * National Center for Supercomputing Applications * + * University of Illinois at Urbana-Champaign * + * 605 E. Springfield, Champaign IL 61820 * + * * + * For conditions of distribution and use, see the accompanying * + * hdf/COPYING file. * + * * + ****************************************************************************/ + +/* $Id$ */ + +/*----------------------------------------------------------------------------- + * File: atom.h + * Purpose: header file for atom API + *---------------------------------------------------------------------------*/ + +/* avoid re-inclusion */ +#ifndef __ATOM_H +#define __ATOM_H + +#include "H5Aproto.h" /* Include Public Definitions */ + +/* Atom Features control */ +/* Define the following macro for fast hash calculations (but limited hash sizes) */ +#define HASH_SIZE_POWER_2 + +/* Define the following macro for atom caching over all the atoms */ +#define ATOMS_ARE_CACHED + +#if defined HDF5_ATOM_MASTER | defined HDF5_ATOM_TESTER +#ifdef ATOMS_ARE_CACHED +/* # of previous atoms cached */ +#define ATOM_CACHE_SIZE 4 +#endif /* ATOMS_ARE_CACHED */ + +/* Map an atom to a Group number */ +#define ATOM_TO_GROUP(a) ((group_t)((((hatom_t)(a))>>((sizeof(hatom_t)*8)-GROUP_BITS))&GROUP_MASK)) + +#ifdef HASH_SIZE_POWER_2 +/* Map an atom to a hash location (assumes s is a power of 2 and smaller than the ATOM_MASK constant) */ +#define ATOM_TO_LOC(a,s) ((hatom_t)(a)&((s)-1)) +#else /* HASH_SIZE_POWER_2 */ +/* Map an atom to a hash location */ +#define ATOM_TO_LOC(a,s) (((hatom_t)(a)&ATOM_MASK)%(s)) +#endif /* HASH_SIZE_POWER_2 */ + +/* Atom information structure used */ +typedef struct atom_info_struct_tag { + hatom_t id; /* atom ID for this info */ + VOIDP *obj_ptr; /* pointer associated with the atom */ + struct atom_info_struct_tag *next; /* link to next atom (in case of hash-clash) */ + }atom_info_t; + +/* Atom group structure used */ +typedef struct atom_group_struct_tag { + uintn count; /* # of times this group has been initialized */ + uintn reserved; /* # of atoms to reserve for constant atoms */ + uintn wrapped; /* whether the id count has wrapped around */ + intn hash_size; /* size of the hash table to store the atoms in */ + uintn atoms; /* current number of atoms held */ + uintn nextid; /* atom ID to use for the next atom */ + atom_info_t **atom_list;/* pointer to an array of ptrs to atoms */ + }atom_group_t; + +/* Define this in only one place */ +#ifdef HDF5_ATOM_MASTER + +/* Array of pointers to atomic groups */ +static atom_group_t *atom_group_list[MAXGROUP]={NULL}; + +/* Pointer to the atom node free list */ +static atom_info_t *atom_free_list=NULL; + +#ifdef ATOMS_ARE_CACHED +/* Array of pointers to atomic groups */ +static hatom_t atom_id_cache[ATOM_CACHE_SIZE]={-1,-1,-1,-1}; +static VOIDP atom_obj_cache[ATOM_CACHE_SIZE]={NULL}; +#endif /* ATOMS_ARE_CACHED */ + +#endif /* HDF5_ATOM_MASTER */ + +/* Useful routines for generally private use */ + +#endif /* HDF5_ATOM_MASTER | HDF5_ATOM_TESTER */ + +#endif /* __ATOM_H */ + diff --git a/src/H5Aproto.h b/src/H5Aproto.h new file mode 100644 index 0000000..2bf2ba5 --- /dev/null +++ b/src/H5Aproto.h @@ -0,0 +1,204 @@ +/**************************************************************************** + * NCSA HDF * + * Software Development Group * + * National Center for Supercomputing Applications * + * University of Illinois at Urbana-Champaign * + * 605 E. Springfield, Champaign IL 61820 * + * * + * For conditions of distribution and use, see the accompanying * + * hdf/COPYING file. * + * * + ****************************************************************************/ + +/* $Id$ */ + +/* + * This file contains function prototypes for each exported function in the H5A module + */ + +#ifndef H5APROTO_H +#define H5APROTO_H + +/* Group values allowed */ +typedef enum {BADGROUP=(-1), /* Invalid Group */ +H5_ERR=0, /* Group ID for Error stack objects */ +H5_FILE, /* Group ID for File objects */ +H5_TEMPLATE, /* Group ID for Template objects */ +H5_DATATYPE, /* Group ID for Datatype objects */ +H5_DATASPACE, /* Group ID for Dataspace objects */ +MAXGROUP /* Highest group in group_t (Invalid as true group) */ +} group_t; + +/* Type of atoms to return to users */ +typedef int32 hatom_t; + +/* Type of the function to compare objects & keys */ +typedef intn (*H5Asearch_func_t)(const VOIDP obj, const VOIDP key); + +/* # of bits to use for Group ID in each atom (change if MAXGROUP>16) */ +#define GROUP_BITS 4 +#define GROUP_MASK 0x0F + +/* # of bits to use for the Atom index in each atom (assumes 8-bit bytes) */ +#define ATOM_BITS ((sizeof(hatom_t)*8)-GROUP_BITS) +#define ATOM_MASK 0x0FFFFFFF + +/* Combine a Group number and an atom index into an atom */ +#define MAKE_ATOM(g,i) ((((hatom_t)(g)&GROUP_MASK)<<((sizeof(hatom_t)*8)-GROUP_BITS))|((hatom_t)(i)&ATOM_MASK)) + +#if defined c_plusplus || defined __cplusplus +extern "C" +{ +#endif /* c_plusplus || __cplusplus */ + +/* Functions in H5A.c */ +/****************************************************************************** + NAME + H5Ainit_group - Initialize an atomic group + + DESCRIPTION + Creates an atomic group to store atoms in. If the group has already been + initialized, this routine just increments the count of # of initializations + and returns without trying to change the size of the hash table. + + RETURNS + Returns SUCCEED if successful and FAIL otherwise + +*******************************************************************************/ +intn H5Ainit_group(group_t grp, /* IN: Group to initialize */ + intn hash_size, /* IN: Minimum hash table size to use for group */ + uintn reserved /* IN: Number of hash table entries to reserve */ +); + +/****************************************************************************** + NAME + H5Adestroy_group - Destroy an atomic group + + DESCRIPTION + Destroys an atomic group which atoms are stored in. If the group still + has atoms which are registered, this routine fails. If there have been + multiple initializations of the group, this routine just decrements the + count of initializations and does not check the atoms out-standing. + + RETURNS + Returns SUCCEED if successful and FAIL otherwise + +*******************************************************************************/ +intn H5Adestroy_group(group_t grp /* IN: Group to destroy */ +); + +/****************************************************************************** + NAME + H5Aregister_atom - Register an object in a group and get an atom for it. + + DESCRIPTION + Registers an object in a group and returns an atom for it. This routine + does _not_ check for unique-ness of the objects, if you register an object + twice, you will get two different atoms for it. This routine does make + certain that each atom in a group is unique. Atoms are created by getting + a unique number for the group the atom is in and incorporating the group + into the atom which is returned to the user. + + RETURNS + Returns atom if successful and FAIL otherwise + +*******************************************************************************/ +hatom_t H5Aregister_atom(group_t grp, /* IN: Group to register the object in */ + const VOIDP object /* IN: Object to attach to atom */ +); + +/****************************************************************************** + NAME + H5Aatom_object - Returns to the object ptr for the atom + + DESCRIPTION + Retrieves the object ptr which is associated with the atom. + + RETURNS + Returns object ptr if successful and NULL otherwise + +*******************************************************************************/ +VOIDP H5Aatom_object(hatom_t atm /* IN: Atom to retrieve object for */ +); + +/****************************************************************************** + NAME + H5Aatom_group - Returns to the group for the atom + + DESCRIPTION + Retrieves the group which is associated with the atom. + + RETURNS + Returns group if successful and FAIL otherwise + +*******************************************************************************/ +group_t H5Aatom_group(hatom_t atm /* IN: Atom to retrieve group for */ +); + +/****************************************************************************** + NAME + H5Aremove_atom - Removes an atom from a group + + DESCRIPTION + Removes an atom from a group. + + RETURNS + Returns atom's object if successful and FAIL otherwise + +*******************************************************************************/ +VOIDP H5Aremove_atom(hatom_t atm /* IN: Atom to remove */ +); + +/****************************************************************************** + NAME + H5Asearch_atom - Search for an object in a group and get it's pointer. + + DESCRIPTION + Searchs for an object in a group and returns the pointer to it. + This routine calls the function pointer passed in for each object in the + group until it finds a match. Currently there is no way to resume a + search. + + RETURNS + Returns pointer an atom's object if successful and NULL otherwise + +*******************************************************************************/ +VOIDP H5Asearch_atom(group_t grp, /* IN: Group to search for the object in */ + H5Asearch_func_t func, /* IN: Ptr to the comparison function */ + const VOIDP key /* IN: pointer to key to compare against */ +); + +/****************************************************************************** + NAME + H5Ais_reserved - Check whether an atom is a reserved atom in a group + + DESCRIPTION + Determines the group an atom belongs to and checks if the atom is a + reserved atom in the group. + + RETURNS + Returns BTRUE/BFALSE/BFAIL + +*******************************************************************************/ +intn H5Ais_reserved(hatom_t atm /* IN: Group to search for the object in */ +); + +/****************************************************************************** + NAME + H5Ashutdown - Terminate various static buffers. + + DESCRIPTION + Free various buffers allocated in the H5A routines. + + RETURNS + Returns SUCCEED/FAIL + +*******************************************************************************/ +intn H5Ashutdown(void); + +#if defined c_plusplus || defined __cplusplus +} +#endif /* c_plusplus || __cplusplus */ + +#endif /* H5APROTO_H */ + diff --git a/src/H5B.c b/src/H5B.c new file mode 100644 index 0000000..f3a7052 --- /dev/null +++ b/src/H5B.c @@ -0,0 +1,1177 @@ +/*------------------------------------------------------------------------- + * Copyright (C) 1997 National Center for Supercomputing Applications. + * All rights reserved. + * + *------------------------------------------------------------------------- + * + * Created: hdf5btree.c + * Jul 10 1997 + * Robb Matzke <robb@maya.nuance.com> + * + * Purpose: Implements balanced, sibling-linked, N-ary trees + * capable of storing any type of data with unique key + * values. + * + * A B-link-tree is a balanced tree where each node has + * a pointer to its left and right siblings. A + * B-link-tree is a rooted tree having the following + * properties: + * + * 1. Every node, x, has the following fields: + * + * a. level[x], the level in the tree at which node + * x appears. Leaf nodes are at level zero. + * + * b. n[x], the number of children pointed to by the + * node. Internal nodes point to subtrees while + * leaf nodes point to arbitrary data. + * + * c. The child pointers themselves, child[x,i] such + * that 0 <= i < n[x]. + * + * d. n[x]+1 key values stored in increasing + * order: + * + * key[x,0] < key[x,1] < ... < key[x,n[x]]. + * + * e. left[x] is a pointer to the node's left sibling + * or the null pointer if this is the left-most + * node at this level in the tree. + * + * f. right[x] is a pointer to the node's right + * sibling or the null pointer if this is the + * right-most node at this level in the tree. + * + * 3. The keys key[x,i] partition the key spaces of the + * children of x: + * + * key[x,i] <= key[child[x,i],j] <= key[x,i+1] + * + * for any valid combination of i and j. + * + * 4. There are lower and upper bounds on the number of + * child pointers a node can contain. These bounds + * can be expressed in terms of a fixed integer k>=2 + * called the `minimum degree' of the B-tree. + * + * a. Every node other than the root must have at least + * k child pointers and k+1 keys. If the tree is + * nonempty, the root must have at least one child + * pointer and two keys. + * + * b. Every node can contain at most 2k child pointers + * and 2k+1 keys. A node is `full' if it contains + * exactly 2k child pointers and 2k+1 keys. + * + * 5. When searching for a particular value, V, and + * key[V] = key[x,i] for some node x and entry i, + * then: + * + * a. If i=0 the child[0] is followed. + * + * b. If i=n[x] the child[n[x]-1] is followed. + * + * c. Otherwise, the child that is followed + * (either child[x,i-1] or child[x,i]) is + * determined by the type of object to which the + * leaf nodes of the tree point and is controlled + * by the key comparison function registered for + * that type of B-tree. + * + * + * Modifications: + * + *------------------------------------------------------------------------- + */ + +/* + * Define this if the root address of a B-link tree should never change. + * + * If this isn't defined and the root node of a tree splits, then the + * new root (which points to the old root plus the new node from the + * split) will be at a new file address. + * + * But if this is defined, then the old root will be copied to a new + * location and the new root will occupy the file memory vacated by the + * old root. + */ +#define H5B_ANCHOR_ROOT + +/* system headers */ +#include <assert.h> +#include "hdf5.h" + +/* private headers */ +#include "H5ACprivate.h" /*cache */ +#include "H5Bprivate.h" /*B-link trees */ +#include "H5MFprivate.h" /*File memory management */ +#include "H5MMprivate.h" /*Core memory management */ + +#define BOUND(MIN,X,MAX) ((MIN)<(X)?(MIN):((MAX)>(X)?(MAX):(X))) +#define false 0 +#define true 1 + +/* PRIVATE PROTOTYPES */ +static off_t H5B_insert_helper (hdf5_file_t *f, off_t addr, + const H5B_class_t *type, + uint8 *lt_key, intn *lt_key_changed, + uint8 *md_key, void *udata, + uint8 *rt_key, intn *rt_key_changed); +static herr_t H5B_flush (hdf5_file_t *f, hbool_t destroy, off_t addr, + H5B_t *b); +static H5B_t *H5B_load (hdf5_file_t *f, off_t addr, const void *_data); +static herr_t H5B_decode_key (hdf5_file_t *f, H5B_t *bt, intn idx); +static size_t H5B_nodesize (hdf5_file_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*(*)(hdf5_file_t*,off_t,const void*))H5B_load, + (herr_t(*)(hdf5_file_t*,hbool_t,off_t,void*))H5B_flush, +}}; + + +/*------------------------------------------------------------------------- + * Function: H5B_new + * + * Purpose: Creates a new empty B-tree leaf node. + * + * Return: Success: address of new node. + * + * Failure: 0 + * + * Programmer: Robb Matzke + * robb@maya.nuance.com + * Jun 23 1997 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +off_t +H5B_new (hdf5_file_t *f, const H5B_class_t *type, size_t sizeof_rkey) +{ + H5B_t *bt=NULL; + off_t addr; + size_t size; + size_t total_native_keysize; + intn offset, i; + + /* + * Allocate file and memory data structures. + */ + size = H5B_nodesize (f, type, &total_native_keysize, sizeof_rkey); + if ((addr = H5MF_alloc (f, size))<=0) return 0; + bt = H5MM_xmalloc (sizeof(H5B_t)); + bt->type = type; + bt->sizeof_rkey = sizeof_rkey; + bt->dirty = 1; + bt->ndirty = 0; + bt->type = type; + bt->level = 0; + bt->left = bt->right = 0; + bt->nchildren = 0; + bt->page = H5MM_xmalloc (size); + bt->native = H5MM_xmalloc (total_native_keysize); + bt->child = H5MM_xmalloc (2*type->k * sizeof(off_t)); + bt->key = H5MM_xmalloc ((2*type->k+1) * sizeof(H5B_key_t)); + + /* + * Initialize each entry's raw child and key pointers to point into the + * `page' buffer. Each native key pointer should be null until the key is + * translated to native format. + */ + for (i=0,offset=H5B_HDR_SIZE(f); + i<2*type->k; + i++,offset+=bt->sizeof_rkey+SIZEOF_OFFSET(f)) { + + bt->key[i].dirty = 0; + bt->key[i].rkey = bt->page + offset; + bt->key[i].nkey = NULL; + bt->child[i] = 0; + } + + /* + * The last possible key... + */ + bt->key[2*type->k].dirty = 0; + bt->key[2*type->k].rkey = bt->page + offset; + bt->key[2*type->k].nkey = NULL; + + /* + * Cache the new B-tree node. + */ + H5AC_set (f, H5AC_BT, addr, bt); + return addr; +} + + +/*------------------------------------------------------------------------- + * Function: H5B_load + * + * Purpose: Loads a B-tree node from the disk. + * + * Return: Success: Pointer to a new B-tree node. + * + * Failure: 0 + * + * Programmer: Robb Matzke + * robb@maya.nuance.com + * Jun 23 1997 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static H5B_t * +H5B_load (hdf5_file_t *f, off_t addr, const void *_data) +{ + const H5B_class_t *type = (const H5B_class_t *)_data; + size_t size, total_nkey_size; + H5B_t *bt = H5MM_xmalloc (sizeof(H5B_t)); + intn i; + uint8 *p; + + assert (type); + assert (type->get_sizeof_rkey); + + + bt->sizeof_rkey = (type->get_sizeof_rkey)(f); + size = H5B_nodesize (f, type, &total_nkey_size, bt->sizeof_rkey); + bt->type = type; + bt->dirty = 0; + bt->ndirty = 0; + bt->page = H5MM_xmalloc (size); + bt->native = H5MM_xmalloc (total_nkey_size); + bt->key = H5MM_xmalloc ((2*type->k+1) * sizeof(H5B_key_t)); + bt->child = H5MM_xmalloc (2 * type->k * sizeof(off_t)); + H5F_block_read (f, addr, size, bt->page); + p = bt->page; + + /* magic number */ + if (memcmp (p, H5B_MAGIC, 4)) goto error; + p += 4; + + /* node type and level */ + if (*p++ != type->id) goto error; + bt->level = *p++; + + /* entries used */ + UINT16DECODE (p, bt->nchildren); + + /* sibling pointers */ + H5F_decode_offset (f, p, bt->left); + H5F_decode_offset (f, p, bt->right); + + /* the child/key pairs */ + for (i=0; i<2*type->k; i++) { + + bt->key[i].dirty = 0; + bt->key[i].rkey = p; + p += bt->sizeof_rkey; + bt->key[i].nkey = NULL; + + if (i<bt->nchildren) { + H5F_decode_offset (f, p, bt->child[i]); + } else { + bt->child[i] = 0; + p += SIZEOF_OFFSET(f); + } + } + + bt->key[2*type->k].dirty = 0; + bt->key[2*type->k].rkey = p; + bt->key[2*type->k].nkey = NULL; + return bt; + +error: + if (bt) { + H5MM_xfree (bt->child); + H5MM_xfree (bt->key); + H5MM_xfree (bt->page); + H5MM_xfree (bt->native); + H5MM_xfree (bt); + } + return NULL; +} + + +/*------------------------------------------------------------------------- + * Function: H5B_flush + * + * Purpose: Flushes a dirty B-tree node to disk. + * + * Return: Success: 0 + * + * Failure: -1 + * + * Programmer: Robb Matzke + * robb@maya.nuance.com + * Jun 23 1997 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static herr_t +H5B_flush (hdf5_file_t *f, hbool_t destroy, off_t addr, H5B_t *bt) +{ + intn i; + size_t size = H5B_nodesize (f, bt->type, NULL, bt->sizeof_rkey); + uint8 *p = bt->page; + + assert (bt->type); + assert (bt->type->encode); + + if (bt->dirty) { + + /* magic number */ + memcpy (p, H5B_MAGIC, 4); + p += 4; + + /* node type and level */ + *p++ = bt->type->id; + *p++ = bt->level; + + /* entries used */ + UINT16ENCODE (p, bt->nchildren); + + /* sibling pointers */ + H5F_encode_offset (f, p, bt->left); + H5F_encode_offset (f, p, bt->right); + + /* child keys and pointers */ + for (i=0; i<=bt->nchildren; i++) { + + /* encode the key */ + assert (bt->key[i].rkey == p); + if (bt->key[i].dirty) { + if (bt->key[i].nkey) { + (bt->type->encode)(f, bt->key[i].rkey, bt->key[i].nkey); + } + bt->key[i].dirty = 0; + } + p += bt->sizeof_rkey; + + /* encode the child address */ + if (i<bt->ndirty) { + H5F_encode_offset (f, p, bt->child[i]); + } else { + p += SIZEOF_OFFSET(f); + } + } + + /* + * Write the disk page. We always write the header, but we don't + * bother writing data for the child entries that don't exist or + * for the final unchanged children. + */ + H5F_block_write (f, addr, size, bt->page); + bt->dirty = 0; + bt->ndirty = 0; + } + + if (destroy) { + H5MM_xfree (bt->child); + H5MM_xfree (bt->key); + H5MM_xfree (bt->page); + H5MM_xfree (bt->native); + H5MM_xfree (bt); + } + return 0; +} + + +/*------------------------------------------------------------------------- + * Function: H5B_find + * + * Purpose: Locate the specified information in a B-tree and return + * that information by filling in fields of the caller-supplied + * UDATA pointer depending on the type of leaf node + * requested. The UDATA can point to additional data passed + * to the key comparison function. + * + * Note: This function does not follow the left/right sibling + * pointers since it assumes that all nodes can be reached + * from the parent node. + * + * Return: Success: 0 if found, values returned through the + * RETVAL argument. + * + * Failure: -1 if not found. + * + * Programmer: Robb Matzke + * robb@maya.nuance.com + * Jun 23 1997 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +herr_t +H5B_find (hdf5_file_t *f, const H5B_class_t *type, off_t addr, void *udata) +{ + H5B_t *bt=NULL; + uint8 lt_key[256], rt_key[256]; + intn idx=-1, lt=0, rt, cmp=1; + + assert (type); + assert (type->sizeof_nkey < sizeof lt_key); + assert (type->decode); + assert (type->cmp); + assert (type->found); + + /* + * Perform a binary search to locate the child which contains + * the thing for which we're searching. The comparison function + * may preempt the B-tree node from the cache. + */ + bt = H5AC_find (f, H5AC_BT, addr, type); + rt = bt->nchildren; + + while (lt<rt && cmp) { + idx = (lt + rt) / 2; + bt = H5AC_find (f, H5AC_BT, addr, type); + if (!bt) return -1; + + /* the left key */ + if (!bt->key[idx].nkey) H5B_decode_key (f, bt, idx); + HDmemcpy (lt_key, bt->key[idx].nkey, type->sizeof_nkey); + + /* the right key */ + if (!bt->key[idx+1].nkey) H5B_decode_key (f, bt, idx+1); + HDmemcpy (rt_key, bt->key[idx+1].nkey, type->sizeof_nkey); + + /* compare */ + if ((cmp=(type->cmp)(f, lt_key, udata, rt_key))<0) { + rt = idx; + } else { + lt = idx+1; + } + } + if (cmp) return -1; + + /* + * Follow the link to the subtree or to the data node. + */ + bt = H5AC_find (f, H5AC_BT, addr, type); + assert (idx>=0 && idx<bt->nchildren); + if (bt->level > 0) { + return H5B_find (f, type, bt->child[idx], udata); + } + + return (type->found)(f, bt->child[idx], lt_key, udata, rt_key); +} + + +/*------------------------------------------------------------------------- + * 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. + * + * Return: Success: Address of the new node. + * + * Failure: 0 + * + * Programmer: Robb Matzke + * robb@maya.nuance.com + * Jul 3 1997 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static off_t +H5B_split (hdf5_file_t *f, const H5B_class_t *type, off_t addr, intn anchor) +{ + H5B_t *old = H5AC_find (f, H5AC_BT, addr, type); + H5B_t *bt = H5MM_xmalloc (sizeof(H5B_t)); + size_t total_nkey_size, size; + intn i, offset; + intn delta = H5B_ANCHOR_LT==anchor ? type->k : 0; + size_t recsize = old->sizeof_rkey + SIZEOF_OFFSET(f); + off_t tmp_addr, new_addr; + H5B_t *tmp=NULL; + + /* + * Create the new B-tree node. + */ + size = H5B_nodesize (f, type, &total_nkey_size, old->sizeof_rkey); + bt->dirty = 1; + bt->ndirty = BOUND (0, old->ndirty-delta, type->k); + bt->type = type; + bt->level = old->level; + bt->nchildren = type->k; + bt->page = H5MM_xmalloc (size); + bt->native = H5MM_xmalloc (total_nkey_size); + bt->child = H5MM_xmalloc (2*type->k * sizeof(off_t)); + bt->key = H5MM_xmalloc ((2*type->k+1) * sizeof(H5B_key_t)); + + /* + * Copy data into the new node from the old node. + */ + memcpy (bt->page + H5B_HDR_SIZE(f), + old->page + H5B_HDR_SIZE(f) + delta*recsize, + type->k * recsize); + memcpy (bt->native, + old->native + delta * type->sizeof_nkey, + (type->k+1) * type->sizeof_nkey); + + for (i=0,offset=H5B_HDR_SIZE(f); i<=2*type->k; i++,offset+=recsize) { + + /* key */ + if (i<=type->k) { + bt->key[i].dirty = old->key[delta+i].dirty; + bt->key[i].rkey = bt->native + offset; + if (old->key[delta+i].nkey) { + bt->key[i].nkey = bt->native + i*type->sizeof_nkey; + } else { + bt->key[i].nkey = NULL; + } + } else { + bt->key[i].dirty = 0; + bt->key[i].rkey = bt->native + offset; + bt->key[i].nkey = NULL; + } + + /* child */ + if (i<type->k) { + bt->child[i] = old->child[delta+i]; + } else if (i<2*type->k) { + bt->child[i] = 0; + } + } + + + /* + * Truncate the old node. + */ + delta = H5B_ANCHOR_LT ? 0 : type->k; + old->dirty += 1; + old->ndirty = BOUND (0, old->ndirty-delta, type->k); + old->nchildren = type->k; + + if (H5B_ANCHOR_RT==anchor) { + memcpy (old->page + H5B_HDR_SIZE(f), + old->page + H5B_HDR_SIZE(f) + delta*recsize, + type->k * recsize); + memmove (old->native, + old->native + delta * type->sizeof_nkey, + (type->k+1) * type->sizeof_nkey); + + for (i=0; i<=2*type->k; i++) { + + if (i<=type->k) { + old->key[i].dirty = old->key[delta+i].dirty; + if (old->key[delta+i].nkey) { + old->key[i].nkey = old->native + i * type->sizeof_nkey; + } else { + old->key[i].nkey = NULL; + } + } else { + old->key[i].nkey = NULL; + } + if (i<type->k) { + old->child[i] = old->child[delta+i]; + } else if (i<2*type->k) { + old->child[i] = 0; + } + } + } + + /* + * Update sibling pointers of new node. + */ + if (H5B_ANCHOR_LT==anchor) { + bt->left = addr; + bt->right = old->right; + } else { + bt->left = old->left; + bt->right = addr; + } + + /* + * Add the new node to the cache. + */ + new_addr = H5MF_alloc (f, size); + H5AC_set (f, H5AC_BT, new_addr, bt); + + /* + * Update sibling pointers of old nodes. + */ + old = H5AC_find (f, H5AC_BT, addr, type); + if (H5B_ANCHOR_LT==anchor) { + old->dirty += 1; + tmp_addr = old->right; + old->right = new_addr; + if (tmp_addr) { + tmp = H5AC_find (f, H5AC_BT, tmp_addr, type); + tmp->dirty += 1; + tmp->left = new_addr; + } + } else { + old->dirty += 1; + tmp_addr = old->left; + old->left = new_addr; + if (tmp_addr) { + tmp = H5AC_find (f, H5AC_BT, tmp_addr, type); + tmp->dirty += 1; + tmp->right = new_addr; + } + } + + return new_addr; +} + + +/*------------------------------------------------------------------------- + * Function: H5B_decode_key + * + * Purpose: Decode the specified key into native format. + * + * Return: Success: 0 + * + * Failure: -1 + * + * Programmer: Robb Matzke + * robb@maya.nuance.com + * Jul 8 1997 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static herr_t +H5B_decode_key (hdf5_file_t *f, H5B_t *bt, intn idx) +{ + bt->key[idx].nkey = bt->native + idx * bt->type->sizeof_nkey; + (bt->type->decode)(f, bt->key[idx].rkey, bt->key[idx].nkey); + return 0; +} + + +/*------------------------------------------------------------------------- + * Function: H5B_insert + * + * Purpose: Adds a new item to the B-tree. If the root node of + * the B-tree splits then the B-tree gets a new address. + * + * Return: Success: Address of the root of the B-tree. The + * B-tree root address may change if the old + * root is split. + * + * Failure: 0 + * + * Programmer: Robb Matzke + * robb@maya.nuance.com + * Jun 23 1997 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +off_t +H5B_insert (hdf5_file_t *f, const H5B_class_t *type, off_t addr, void *udata) +{ + uint8 lt_key[256], md_key[256], rt_key[256]; + intn lt_key_changed=false, rt_key_changed=false; + off_t child, new_root; + intn level; + H5B_t *bt; + + assert (type); + assert (type->sizeof_nkey < sizeof lt_key); + + child = H5B_insert_helper (f, addr, type, lt_key, <_key_changed, + md_key, udata, rt_key, &rt_key_changed); + if (child<0) return 0; + if (0==child) return addr; + + /* the current root */ + bt = H5AC_find (f, H5AC_BT, addr, type); + level = bt->level; + if (!lt_key_changed) { + if (!bt->key[0].nkey) H5B_decode_key (f, bt, 0); + memcpy (lt_key, bt->key[0].nkey, type->sizeof_nkey); + } + + /* the new node */ + bt = H5AC_find (f, H5AC_BT, child, type); + if (!rt_key_changed) { + if (!bt->key[bt->nchildren].nkey) H5B_decode_key (f, bt, bt->nchildren); + memcpy (rt_key, bt->key[bt->nchildren].nkey, type->sizeof_nkey); + } + +#ifdef H5B_ANCHOR_ROOT + { + /* + * Copy the old root node to some other file location and make the new + * root at the old root's previous address. This prevents the B-tree + * from "moving". + */ + size_t size = H5B_nodesize (f, type, NULL, bt->sizeof_rkey); + uint8 *buf = H5MM_xmalloc (size); + off_t tmp_addr = H5MF_alloc (f, size); + + H5AC_flush (f, H5AC_BT, addr, FALSE); + H5F_block_read (f, addr, size, buf); + H5F_block_write (f, tmp_addr, size, buf); + H5AC_rename (f, H5AC_BT, addr, tmp_addr); + + buf = H5MM_xfree (buf); + new_root = addr; + addr = tmp_addr; + + /* update the new child's left pointer */ + bt = H5AC_find (f, H5AC_BT, child, type); + bt->dirty += 1; + bt->left = addr; + + /* clear the old root at the old address */ + bt = H5AC_find (f, H5AC_BT, new_root, type); + bt->dirty += 1; + bt->ndirty = 0; + bt->left = 0; + bt->right = 0; + bt->nchildren = 0; + } +#else + /* + * The new root is created at a new file location. + */ + new_root = H5B_new (f, type, bt->sizeof_rkey); +#endif + + /* the new root */ + bt = H5AC_find (f, H5AC_BT, new_root, type); + bt->dirty += 1; + bt->ndirty = 2; + bt->level = level+1; + bt->nchildren = 2; + + bt->child[0] = addr; + bt->key[0].dirty = 1; + bt->key[0].nkey = bt->native; + memcpy (bt->key[0].nkey, lt_key, type->sizeof_nkey); + + bt->child[1] = child; + bt->key[1].dirty = 1; + bt->key[1].nkey = bt->native + type->sizeof_nkey; + memcpy (bt->key[1].nkey, md_key, type->sizeof_nkey); + + bt->key[2].dirty = 1; + bt->key[2].nkey = bt->native + 2 * type->sizeof_nkey; + memcpy (bt->key[2].nkey, rt_key, type->sizeof_nkey); + + return new_root; +} + + +/*------------------------------------------------------------------------- + * Function: H5B_insert_child + * + * Purpose: Insert a child at the specified address with the + * specified left or right key. + * + * Return: void + * + * Programmer: Robb Matzke + * robb@maya.nuance.com + * Jul 8 1997 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static void +H5B_insert_child (hdf5_file_t *f, const H5B_class_t *type, off_t addr, + intn idx, off_t child, intn anchor, void *md_key) +{ + H5B_t *bt; + size_t recsize; + intn i; + + bt = H5AC_find (f, H5AC_BT, addr, type); + assert (bt); + bt->dirty += 1; + recsize = bt->sizeof_rkey + SIZEOF_OFFSET(f); + + if (H5B_ANCHOR_LT==anchor) { + /* + * The MD_KEY is the left key of the new node. + */ + memmove (bt->page + H5B_HDR_SIZE(f) + (idx+1)*recsize, + bt->page + H5B_HDR_SIZE(f) + idx*recsize, + (bt->nchildren-idx)*recsize + bt->sizeof_rkey); + + memmove (bt->native + (idx+1) * type->sizeof_nkey, + bt->native + idx * type->sizeof_nkey, + ((bt->nchildren-idx)+1) * type->sizeof_nkey); + + for (i=bt->nchildren; i>=idx; --i) { + bt->key[i+1].dirty = bt->key[i].dirty; + } + bt->key[idx].dirty = 1; + bt->key[idx].nkey = bt->native + idx * type->sizeof_nkey; + memcpy (bt->key[idx].nkey, md_key, type->sizeof_nkey); + + } else { + /* + * The MD_KEY is the right key of the new node. + */ + memmove (bt->page + (H5B_HDR_SIZE(f) + + (idx+1)*recsize + bt->sizeof_rkey), + bt->page + (H5B_HDR_SIZE(f) + + idx*recsize + bt->sizeof_rkey), + (bt->nchildren-idx) * recsize); + + memmove (bt->native + idx + 2, + bt->native + idx + 1, + (bt->nchildren-idx) * type->sizeof_nkey); + + for (i=bt->nchildren; i>idx; --i) { + bt->key[i+1].dirty = bt->key[i].dirty; + } + bt->key[idx+1].dirty = 1; + bt->key[idx+1].nkey = bt->native + + (idx+1) * type->sizeof_nkey; + memcpy (bt->key[idx+1].nkey, md_key, type->sizeof_nkey); + } + + memmove (bt->child + idx + 1, + bt->child + idx, + (bt->nchildren - idx) * sizeof(off_t)); + + bt->child[idx] = child; + bt->nchildren += 1; + bt->ndirty = bt->nchildren; +} + + +/*------------------------------------------------------------------------- + * Function: H5B_insert_helper + * + * Purpose: Inserts the item UDATA into the tree rooted at ADDR and having + * the specified type. + * + * On return, if LT_KEY_CHANGED is non-zero, then LT_KEY is + * the new native left key. Similarily for RT_KEY_CHANGED + * and RT_KEY. + * + * If the node splits, then MD_KEY contains the key that + * was split between the two nodes (that is, the key that + * appears as the max key in the left node and the min key + * in the right node). + * + * Return: Success: Address of the new node if the node + * splits. The new node is always to the + * right of the previous node. + * + * 0 if the node didn't split. The MD_KEY + * buffer is undefined. + * + * Failure: -1 + * + * Programmer: Robb Matzke + * robb@maya.nuance.com + * Jul 9 1997 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static off_t +H5B_insert_helper (hdf5_file_t *f, off_t addr, const H5B_class_t *type, + uint8 *lt_key, intn *lt_key_changed, + uint8 *md_key, void *udata, + uint8 *rt_key, intn *rt_key_changed) +{ + H5B_t *bt; + intn lt=0, idx=-1, rt, cmp=-1; + intn anchor; + off_t child, twin=0; + + assert (type); + assert (type->decode); + assert (type->cmp); + assert (type->new); + + /* + * Use a binary search to find the child that will receive the new + * data. The comparison function may preempt the B-tree node from + * the cache each time through the loop. When the search completes + * IDX points to the child that should get the new data. + */ + bt = H5AC_find (f, H5AC_BT, addr, type); + if (!bt) goto error; + rt = bt->nchildren; + + while (lt<rt && cmp) { + idx = (lt + rt) / 2; + bt = H5AC_find (f, H5AC_BT, addr, type); + if (!bt) goto error; + + /* left key */ + if (!bt->key[idx].nkey) H5B_decode_key (f, bt, idx); + memcpy (lt_key, bt->key[idx].nkey, type->sizeof_nkey); + + /* right key */ + if (!bt->key[idx+1].nkey) H5B_decode_key (f, bt, idx+1); + memcpy (rt_key, bt->key[idx+1].nkey, type->sizeof_nkey); + + /* compare */ + if ((cmp=(type->cmp)(f, lt_key, udata, rt_key))<0) { + rt = idx; + } else { + lt = idx+1; + } + } + + /* + * Adjust for boundary conditions. If adjusting at the leaf level + * update the left and right key buffers since the data node insert + * function needs them as input. Don't worry about it at higher node + * levels because this function uses them for output only. + */ + bt = H5AC_find (f, H5AC_BT, addr, type); + if (cmp<0 && idx<=0) { + idx = 0; + cmp = 0; + if (0==bt->level && bt->nchildren) { + if (!bt->key[idx].nkey) H5B_decode_key (f, bt, idx); + memcpy (lt_key, bt->key[idx].nkey, type->sizeof_nkey); + if (!bt->key[idx+1].nkey) H5B_decode_key (f, bt, idx+1); + memcpy (rt_key, bt->key[idx+1].nkey, type->sizeof_nkey); + } + } else if (cmp>0 && idx+1>=bt->nchildren) { + idx = bt->nchildren-1; + cmp = 0; + if (0==bt->level && bt->nchildren) { + if (!bt->key[idx].nkey) H5B_decode_key (f, bt, idx); + memcpy (lt_key, bt->key[idx].nkey, type->sizeof_nkey); + if (!bt->key[idx+1].nkey) H5B_decode_key (f, bt, idx+1); + memcpy (rt_key, bt->key[idx+1].nkey, type->sizeof_nkey); + } + } + assert (0==cmp); + + /* + * If there are no children, then create a new child. This can only + * happen at the root of the B-tree. Creating a new child may + * preempt the B-tree node from the cache. The left and right key + * buffers are output values. + */ + if (0==bt->nchildren) { + child = (type->new)(f, lt_key, udata, rt_key); + if (child<=0) goto error; + bt = H5AC_find (f, H5AC_BT, addr, type); + bt->nchildren = 1; + bt->dirty += 1; + bt->ndirty = 1; + bt->child[0] = child; + + bt->key[0].dirty = 1; + bt->key[0].nkey = bt->native; + memcpy (bt->key[0].nkey, lt_key, type->sizeof_nkey); + + bt->key[1].dirty = 1; + bt->key[1].nkey = bt->native + type->sizeof_nkey; + memcpy (bt->key[1].nkey, rt_key, type->sizeof_nkey); + idx = 0; + } + + /* + * Insert the new data in the child B-tree node or in the data node. + */ + if (bt->level > 0) { + child = H5B_insert_helper (f, bt->child[idx], type, + lt_key, lt_key_changed, + md_key, udata, + rt_key, rt_key_changed); + anchor = H5B_ANCHOR_LT; + } else { + child = (type->insert)(f, bt->child[idx], &anchor, + lt_key, lt_key_changed, + md_key, udata, + rt_key, rt_key_changed); + } + if (child<0) goto error; + bt = H5AC_find (f, H5AC_BT, addr, type); + + /* + * Update the left and right keys. + */ + if (*lt_key_changed) { + bt->key[idx].nkey = bt->native + idx * type->sizeof_nkey; + memcpy (bt->key[idx].nkey, lt_key, type->sizeof_nkey); + bt->dirty += 1; + bt->key[idx].dirty = 1; + if (idx>0) *lt_key_changed = false; + } + if (*rt_key_changed) { + bt->key[idx+1].nkey = bt->native + + (idx+1) * type->sizeof_nkey; + memcpy (bt->key[idx+1].nkey, rt_key, type->sizeof_nkey); + bt->dirty += 1; + bt->key[idx+1].dirty = 1; + if (idx+1<bt->nchildren) *rt_key_changed = false; + } + + /* + * If the child split and the left node is anchored, then the new + * child node gets inserted to the right of our current position. + */ + if (child && H5B_ANCHOR_LT==anchor) idx++; + + /* + * Split this node if the child node split and this node is full. + * Make sure `addr' points to the node that gets the new child + * and that `idx' is adjusted appropriately. + */ + if (child && bt->nchildren==2*type->k) { + twin = H5B_split (f, type, addr, anchor); + if (idx<=type->k) { + addr = H5B_ANCHOR_LT==anchor ? addr : twin; + } else { + idx -= type->k; + addr = H5B_ANCHOR_LT==anchor ? twin : addr; + } + } + + /* + * If the child split, then insert the new child. + */ + if (child) { + H5B_insert_child (f, type, addr, idx, child, anchor, md_key); + } + + /* + * If this node split, return the mid key (the one that is shared + * by the left and right node). + */ + if (twin) { + bt = H5AC_find (f, H5AC_BT, twin, type); + if (H5B_ANCHOR_LT==anchor) { + if (!bt->key[0].nkey) { + H5B_decode_key (f, bt, 0); + } + memcpy (md_key, bt->key[0].nkey, type->sizeof_nkey); + } else { + if (!bt->key[bt->nchildren].nkey) { + H5B_decode_key (f, bt, bt->nchildren); + } + memcpy (md_key, bt->key[bt->nchildren].nkey, type->sizeof_nkey); + } + } + + return twin; + +error: + return -1; +} + + +/*------------------------------------------------------------------------- + * Function: H5B_list + * + * Purpose: Calls the list callback for each leaf node of the + * B-tree, passing it the UDATA structure. + * + * Return: Success: 0 + * + * Failure: -1 + * + * Programmer: Robb Matzke + * robb@maya.nuance.com + * Jun 23 1997 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +herr_t +H5B_list (hdf5_file_t *f, const H5B_class_t *type, off_t addr, void *udata) +{ + H5B_t *bt; + off_t *child=NULL; + off_t twin; + intn i, nchildren, status; + herr_t (*list)(hdf5_file_t*,off_t,void*); + + assert (type); + assert (type->list); + + bt = H5AC_find (f, H5AC_BT, addr, type); + if (!bt) return -1; + + if (bt->level>0) { + return H5B_list (f, type, bt->child[0], udata); + } else { + child = H5MM_xmalloc (2 * type->k * sizeof(off_t)); + list = type->list; + twin = addr; + + while (twin) { /*for each leaf node*/ + bt = H5AC_find (f, H5AC_BT, twin, type); + if (!bt) { + H5MM_xfree (child); + return -1; + } + nchildren = bt->nchildren; + twin = bt->right; + HDmemcpy (child, bt->child, nchildren * sizeof(off_t)); + bt = NULL; /*list callback may invalidate the cache*/ + + for (i=0; i<nchildren; i++) { + status = (list)(f, child[i], udata); + if (status<0) { + H5MM_xfree (child); + return -1; + } + } + } + H5MM_xfree (child); + } + return 0; +} + + +/*------------------------------------------------------------------------- + * Function: H5B_nodesize + * + * Purpose: Returns the number of bytes needed for this type of + * B-tree node. The size is the size of the header plus + * enough space for 2t child pointers and 2t+1 keys. + * + * If TOTAL_NKEY_SIZE is non-null, what it points to will + * be initialized with the total number of bytes required to + * hold all the key values in native order. + * + * Return: Success: Size of node in file. + * + * Failure: never fails. + * + * Programmer: Robb Matzke + * robb@maya.nuance.com + * Jul 3 1997 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static size_t +H5B_nodesize (hdf5_file_t *f, const H5B_class_t *type, + size_t *total_nkey_size, size_t sizeof_rkey) +{ + if (total_nkey_size) { + *total_nkey_size = (2 * type->k + 1) * type->sizeof_nkey; + } + + return (H5B_HDR_SIZE(f) + /*node header */ + 2 * type->k * SIZEOF_OFFSET(f) + /*child pointers*/ + (2*type->k+1) * sizeof_rkey); /*keys */ +} + diff --git a/src/H5Bprivate.h b/src/H5Bprivate.h new file mode 100644 index 0000000..d6ecc7c --- /dev/null +++ b/src/H5Bprivate.h @@ -0,0 +1,85 @@ +/*------------------------------------------------------------------------- + * Copyright (C) 1997 National Center for Supercomputing Applications. + * All rights reserved. + * + *------------------------------------------------------------------------- + * + * Created: H5Bprivate.h + * Jul 10 1997 + * Robb Matzke <matzke@llnl.gov> + * + * Purpose: Private non-prototype header. + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +#ifndef _H5Bprivate_H +#define _H5Bprivate_H + +#include "H5Bproto.h" /*API prototypes */ + + + +#define H5B_MAGIC "TREE" /* tree node magic number */ +#define H5B_HDR_SIZE(F) (8+2*SIZEOF_OFFSET(F)) + +#define H5B_ANCHOR_LT 0 /* left node is anchored, right is new */ +#define H5B_ANCHOR_RT 1 /* right node is anchored, left is new */ + + +/* + * Each class of object that can be pointed to by a B-link tree has a + * variable of this type that contains class variables and methods. + */ +typedef struct H5B_class_t { + intn id; /*id as found in file */ + intn k; /* max children is 2k */ + size_t sizeof_nkey; /*size of native (memory) key */ + size_t (*get_sizeof_rkey)(hdf5_file_t*); + off_t (*new)(hdf5_file_t*,void*,void*,void*); + intn (*cmp)(hdf5_file_t*,void*,void*,void*); + herr_t (*found)(hdf5_file_t*,off_t,void*,void*,void*); + off_t (*insert)(hdf5_file_t*,off_t,int*,void*,int*,void*,void*, + void*,int*); + herr_t (*list)(hdf5_file_t*,off_t,void*); + void (*decode)(hdf5_file_t*,uint8*,void*); + void (*encode)(hdf5_file_t*,uint8*,void*); +} H5B_class_t; + +/* + * The B-tree node as stored in memory... + */ +typedef struct H5B_key_t { + intn dirty; /*native key is more recent than raw key*/ + uint8 *rkey; /*ptr into node->page for raw key */ + void *nkey; /*null or ptr into node->native for key */ +} H5B_key_t; + +typedef struct H5B_t { + const H5B_class_t *type; /*type of tree */ + size_t sizeof_rkey; /*size of raw (disk) key */ + intn dirty; /*something in the tree is dirty */ + intn ndirty; /*num child ptrs to emit */ + intn level; /*node level */ + off_t left; /*address of left sibling */ + off_t right; /*address of right sibling */ + intn nchildren; /*number of child pointers */ + uint8 *page; /*disk page */ + uint8 *native; /*array of keys in native format */ + H5B_key_t *key; /*2k+1 key entries */ + off_t *child; /*2k child pointers */ +} H5B_t; + + +/* + * Library prototypes. + */ +herr_t H5B_debug (hdf5_file_t *f, off_t addr, const H5B_class_t *type); +off_t H5B_new (hdf5_file_t *f, const H5B_class_t *type, size_t sizeof_rkey); +herr_t H5B_find (hdf5_file_t *f, const H5B_class_t *type, off_t addr, void *udata); +off_t H5B_insert (hdf5_file_t *f, const H5B_class_t *type, off_t addr, void *udata); +herr_t H5B_list (hdf5_file_t *f, const H5B_class_t *type, off_t addr, void *udata); + + +#endif /* !_H5Bprivate_H */ diff --git a/src/H5Bproto.h b/src/H5Bproto.h new file mode 100644 index 0000000..3869db4 --- /dev/null +++ b/src/H5Bproto.h @@ -0,0 +1,29 @@ +/*------------------------------------------------------------------------- + * Copyright (C) 1997 National Center for Supercomputing Applications. + * All rights reserved. + * + *------------------------------------------------------------------------- + * + * Created: H5Bproto.h + * Jul 10 1997 + * Robb Matzke <robb@maya.nuance.com> + * + * Purpose: Non-API function prototypes for B-link trees. + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +#ifndef _H5Bproto_H +#define _H5Bproto_H + +#if defined c_plusplus || defined __cplusplus +extern "C" +{ +#endif + +#if defined c_plusplus || defined __cplusplus +} +#endif + +#endif diff --git a/src/H5C.c b/src/H5C.c new file mode 100644 index 0000000..847f3b5 --- /dev/null +++ b/src/H5C.c @@ -0,0 +1,506 @@ +/**************************************************************************** +* NCSA HDF * +* Software Development Group * +* National Center for Supercomputing Applications * +* University of Illinois at Urbana-Champaign * +* 605 E. Springfield, Champaign IL 61820 * +* * +* For conditions of distribution and use, see the accompanying * +* hdf/COPYING file. * +* * +****************************************************************************/ + +#ifdef RCSID +static char RcsId[] = "@(#)$Revision$"; +#endif + +/* $Id$ */ + +/*LINTLIBRARY */ +/*+ + FILE + hdf5file.c + HDF5 "personality template" routines + + EXPORTED ROUTINES + H5Csetparm -- Set a parameter for a template + H5Cgetparm -- Get a parameter for a template + + LIBRARY-SCOPED ROUTINES + + LOCAL ROUTINES + H5C_init_interface -- initialize the interface + + */ + +#include "hdf5.h" + +/* private header files */ +#include "H5private.h" /* Generic Functions */ +#include "H5Cprivate.h" /* Template information */ + +/*--------------------- Locally scoped variables -----------------------------*/ + +/* Whether we've installed the library termination function yet for this interface */ +static intn interface_initialize = FALSE; + +/* Define the library's default file creation template (constants in hdf5lims.h) */ +const file_create_temp_t default_file_create={ + HDF5_USERBLOCK_DEFAULT, /* Default user-block size */ + HDF5_OFFSETSIZE_DEFAULT, /* Default offset size */ + HDF5_LENGTHSIZE_DEFAULT, /* Default length size */ + HDF5_BTREEPAGE_DEFAULT, /* Default B-tree page size */ + HDF5_BOOTBLOCK_VERSION, /* Current Boot-Block version # */ + HDF5_SMALLOBJECT_VERSION, /* Current Small-Object heap version # */ + HDF5_FREESPACE_VERSION, /* Current Free-Space info version # */ + HDF5_OBJECTDIR_VERSION, /* Current Object Directory info version # */ + HDF5_SHAREDHEADER_VERSION /* Current Shared-Header format version # */ +}; +static hatom_t default_file_id=FAIL; /* Atom for the default file-creation template */ + +/*--------------------- Local function prototypes ----------------------------*/ +static herr_t H5C_init_interface(void); + +/*-------------------------------------------------------------------------- +NAME + H5C_init_interface -- Initialize interface-specific information +USAGE + herr_t H5C_init_interface() + +RETURNS + SUCCEED/FAIL +DESCRIPTION + Initializes any interface-specific data or routines. + +--------------------------------------------------------------------------*/ +static herr_t H5C_init_interface(void) +{ +#ifdef LATER + CONSTR(FUNC, "H5C_init_interface"); /* For HERROR */ +#endif /* LATER */ + herr_t ret_value = SUCCEED; + + /* Don't use "FUNC_ENTER" macro, to avoid potential infinite recursion */ + PABLO_TRACE_ON(H5C_mask, ID_H5C_init_interface); + + /* Don't call this routine again... */ + interface_initialize = TRUE; + + /* Initialize the atom group for the file IDs */ + ret_value=H5Ainit_group(H5_TEMPLATE,HDF5_TEMPID_HASHSIZE,0); + + FUNC_LEAVE(H5C_mask, ID_H5C_init_interface, ret_value); +} /* H5C_init_interface */ + +/*-------------------------------------------------------------------------- + NAME + H5C_get_default_atom + PURPOSE + Retrive an atom for a default HDF5 template. + USAGE + hatom_t H5C_create(type) + hobjtype_t type; IN: Type of object to retrieve default template of + RETURNS + Returns template ID (atom) of the default object for a template type on + success, FAIL on failure + DESCRIPTION + This is function retrieves atoms for the default templates for the + different types of HDF5 templates. +--------------------------------------------------------------------------*/ +hatom_t H5C_get_default_atom(hobjtype_t type) +{ + CONSTR(FUNC, "H5C_create"); /* for HERROR */ + hatom_t ret_value = FAIL; + + FUNC_ENTER(H5C_mask, ID_H5C_get_default_atom, H5C_init_interface, FAIL); + + /* Clear errors and check args and all the boring stuff. */ + H5ECLEAR; + + switch(type) + { + case H5_TEMPLATE: + if(default_file_id==FAIL) + { + if((default_file_id=H5Aregister_atom(H5_TEMPLATE, (const VOIDP)&default_file_create))==FAIL) + HGOTO_ERROR(H5E_ATOM, H5E_CANTREGISTER, FAIL); + } /* end else */ + HGOTO_DONE(default_file_id); + break; + + default: + HGOTO_ERROR(H5E_ARGS, H5E_BADRANGE, FAIL); + } /* end switch */ + +done: + if(ret_value == FAIL) + { /* Error condition cleanup */ + + } /* end if */ + + /* Normal function cleanup */ + + FUNC_LEAVE(H5C_mask, ID_H5C_get_default_atom, ret_value); +} /* end H5C_get_default_atom() */ + +/*-------------------------------------------------------------------------- + NAME + H5C_init + PURPOSE + Initialize a new HDF5 template with a copy of an existing template. + USAGE + herr_t H5C_init(dst_atm, src) + hatom_t dst_atm; IN: Atom for the template to initialize + file_create_temp_t *src; IN: Template to use to initialize with + RETURNS + SUCCEED/FAIL + DESCRIPTION + This function copies the contents of the source template into the + newly created destination template. +--------------------------------------------------------------------------*/ +herr_t H5C_init(hatom_t dst_atm, const file_create_temp_t *src) +{ + CONSTR(FUNC, "H5C_init"); /* for HERROR */ + file_create_temp_t *dst; /* destination template */ + herr_t ret_value = SUCCEED; /* return value */ + + FUNC_ENTER(H5C_mask, ID_H5C_init, H5C_init_interface, FAIL); + + /* Clear errors and check args and all the boring stuff. */ + H5ECLEAR; + if(src==NULL) + HGOTO_ERROR(H5E_ARGS, H5E_BADRANGE, FAIL); + + /* Get the template to initialize */ + if((dst=H5Aatom_object(dst_atm))==NULL) + HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL); + + /* Copy in the source template */ + HDmemcpy(dst,src,sizeof(file_create_temp_t)); + +done: + if(ret_value == FAIL) + { /* Error condition cleanup */ + + } /* end if */ + + /* Normal function cleanup */ + + FUNC_LEAVE(H5C_mask, ID_H5C_init, ret_value); +} /* end H5C_init() */ + +/*-------------------------------------------------------------------------- + NAME + H5C_create + PURPOSE + Create a new HDF5 template. + USAGE + hatom_t H5C_create(owner_id, type, name) + hatom_t owner_id; IN: Group/file which owns this template + hobjtype_t type; IN: Type of template to create + const char *name; IN: Name of the template to create + RETURNS + Returns template ID (atom) on success, FAIL on failure + DESCRIPTION + This is the primary function for creating different HDF5 templates. + Currently the name of template is not used and may be NULL. +--------------------------------------------------------------------------*/ +hatom_t H5C_create(hatom_t owner_id, hobjtype_t type, const char *name) +{ + CONSTR(FUNC, "H5C_create"); /* for HERROR */ + hatom_t ret_value = FAIL; /* atom for template object to return */ + + FUNC_ENTER(H5C_mask, ID_H5C_create, H5C_init_interface, FAIL); + + /* Clear errors and check args and all the boring stuff. */ + H5ECLEAR; + + switch(type) + { + case H5_TEMPLATE: + { + file_create_temp_t *new_create_temp; /* new template object to create */ + + if((new_create_temp=HDmalloc(sizeof(file_create_temp_t)))==NULL) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL); + if((ret_value=H5Aregister_atom(H5_TEMPLATE, (const VOIDP)new_create_temp))==FAIL) + HGOTO_ERROR(H5E_ATOM, H5E_CANTREGISTER, FAIL); + } /* end case/block */ + break; + + default: + HGOTO_ERROR(H5E_ARGS, H5E_BADRANGE, FAIL); + } /* end switch */ + +done: + if(ret_value == FAIL) + { /* Error condition cleanup */ + + } /* end if */ + + /* Normal function cleanup */ + + FUNC_LEAVE(H5C_mask, ID_H5C_create, ret_value); +} /* end H5C_create() */ + +/*-------------------------------------------------------------------------- + NAME + H5C_release + PURPOSE + Release access to a template object. + USAGE + herr_t H5C_release(oid) + hatom_t oid; IN: Template object to release access to + RETURNS + SUCCEED/FAIL + DESCRIPTION + This function releases access to a template object +--------------------------------------------------------------------------*/ +herr_t H5C_release(hatom_t oid) +{ + CONSTR(FUNC, "H5C_release"); /* for HERROR */ + file_create_temp_t *template; /* template to destroy */ + herr_t ret_value = SUCCEED; + + FUNC_ENTER(H5C_mask, ID_H5C_release, H5C_init_interface, FAIL); + + /* Clear errors and check args and all the boring stuff. */ + H5ECLEAR; + + /* Chuck the object! :-) */ + if((template=H5Aremove_atom(oid))==NULL) + HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL); + HDfree(template); + +done: + if(ret_value == FAIL) + { /* Error condition cleanup */ + + } /* end if */ + + /* Normal function cleanup */ + + FUNC_LEAVE(H5C_mask, ID_H5C_release, ret_value); +} /* end H5C_release() */ + +/*-------------------------------------------------------------------------- + NAME + H5Cgetparm + PURPOSE + Get a parameter from a template + USAGE + herr_t H5Cgetparm(tid, parm, buf) + hatom_t tid; IN: Template object to retrieve parameter from + file_create_param_t parm; IN: Paramter to retrieve + VOIDP buf; OUT: Pointer to buffer to store parameter in + RETURNS + SUCCEED/FAIL + DESCRIPTION + This function retrieves the value of a specific parameter from a + template +--------------------------------------------------------------------------*/ +herr_t H5Cgetparm(hatom_t tid, file_create_param_t parm, VOIDP buf) +{ + CONSTR(FUNC, "H5Cgetparm"); /* for HERROR */ + file_create_temp_t *template; /* template to query */ + herr_t ret_value = SUCCEED; + + FUNC_ENTER(H5C_mask, ID_H5Cgetparm, H5C_init_interface, FAIL); + + /* Clear errors and check args and all the boring stuff. */ + H5ECLEAR; + if(buf==NULL) + HGOTO_ERROR(H5E_ARGS, H5E_BADRANGE, FAIL); + + /* Get a pointer the template to query */ + if((template=H5Aatom_object(tid))==NULL) + HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL); + + switch(parm) + { + case H5_USERBLOCK_SIZE: + *(uintn *)buf=template->userblock_size; + break; + + case H5_OFFSET_SIZE: + *(uintn *)buf=template->offset_size; + break; + + case H5_LENGTH_SIZE: + *(uintn *)buf=template->length_size; + break; + + case H5_BTREE_SIZE: + *(uintn *)buf=template->btree_page_size; + break; + + case H5_BOOTBLOCK_VER: + *(uint8 *)buf=template->bootblock_ver; + break; + + case H5_SMALLOBJECT_VER: + *(uint8 *)buf=template->smallobject_ver; + break; + + case H5_FREESPACE_VER: + *(uint8 *)buf=template->freespace_ver; + break; + + case H5_OBJECTDIR_VER: + *(uint8 *)buf=template->objectdir_ver; + break; + + case H5_SHAREDHEADER_VER: + *(uint8 *)buf=template->sharedheader_ver; + break; + + default: + HGOTO_ERROR(H5E_ARGS, H5E_BADRANGE, FAIL); + } /* end switch */ + +done: + if(ret_value == FAIL) + { /* Error condition cleanup */ + + } /* end if */ + + /* Normal function cleanup */ + + FUNC_LEAVE(H5C_mask, ID_H5Cgetparm, ret_value); +} /* end H5Cgetparm() */ + +/*-------------------------------------------------------------------------- + NAME + H5Csetparm + PURPOSE + Set a parameter from a template + USAGE + herr_t H5Csetparm(tid, parm, buf) + hatom_t tid; IN: Template object to store parameter in + file_create_param_t parm; IN: Parameter to store + VOIDP buf; OUT: Pointer to parameter buffer + RETURNS + SUCCEED/FAIL + DESCRIPTION + This function stores the value of a specific parameter for a template +--------------------------------------------------------------------------*/ +herr_t H5Csetparm(hatom_t tid, file_create_param_t parm, const VOIDP buf) +{ + CONSTR(FUNC, "H5Csetparm"); /* for HERROR */ + file_create_temp_t *template; /* template to query */ + herr_t ret_value = SUCCEED; + + FUNC_ENTER(H5C_mask, ID_H5Csetparm, H5C_init_interface, FAIL); + + /* Clear errors and check args and all the boring stuff. */ + H5ECLEAR; + if(buf==NULL) + HGOTO_ERROR(H5E_ARGS, H5E_BADRANGE, FAIL); + + /* Get a pointer the template to query */ + if((template=H5Aatom_object(tid))==NULL) + HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL); + + switch(parm) + { + case H5_USERBLOCK_SIZE: + template->userblock_size=*(const uintn *)buf; + break; + + case H5_OFFSET_SIZE: + template->offset_size=*(const uintn *)buf; + break; + + case H5_LENGTH_SIZE: + template->length_size=*(const uintn *)buf; + break; + + case H5_BTREE_SIZE: + template->btree_page_size=*(const uintn *)buf; + break; + + case H5_BOOTBLOCK_VER: + template->bootblock_ver=*(const uint8 *)buf; + break; + + case H5_SMALLOBJECT_VER: + template->smallobject_ver=*(const uint8 *)buf; + break; + + case H5_FREESPACE_VER: + template->freespace_ver=*(const uint8 *)buf; + break; + + case H5_OBJECTDIR_VER: + template->objectdir_ver=*(const uint8 *)buf; + break; + + case H5_SHAREDHEADER_VER: + template->sharedheader_ver=*(const uint8 *)buf; + break; + + default: + HGOTO_ERROR(H5E_ARGS, H5E_BADRANGE, FAIL); + } /* end switch */ + +done: + if(ret_value == FAIL) + { /* Error condition cleanup */ + + } /* end if */ + + /* Normal function cleanup */ + + FUNC_LEAVE(H5C_mask, ID_H5Csetparm, ret_value); +} /* end H5Csetparm() */ + +/*-------------------------------------------------------------------------- + NAME + H5C_copy + PURPOSE + Copy a template + USAGE + hatom_t H5C_copy(tid) + hatom_t tid; IN: Template object to copy + RETURNS + Returns template ID (atom) on success, FAIL on failure + DESCRIPTION + This function creates a new copy of a template with all the same parameter + settings. +--------------------------------------------------------------------------*/ +hatom_t H5C_copy(hatom_t tid) +{ + CONSTR(FUNC, "H5C_copy"); /* for HERROR */ + file_create_temp_t *template, *new_template; /* template to query */ + herr_t ret_value = SUCCEED; + + FUNC_ENTER(H5C_mask, ID_H5C_copy, H5C_init_interface, FAIL); + + /* Clear errors and check args and all the boring stuff. */ + H5ECLEAR; + + /* Get a pointer the template to query */ + if((template=H5Aatom_object(tid))==NULL) + HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL); + + /* Allocate space for the new template */ + if((new_template=HDmalloc(sizeof(file_create_temp_t)))==NULL) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL); + + /* Copy over the information from the old template */ + HDmemcpy(new_template,template,sizeof(file_create_temp_t)); + + /* Register the atom for the new template */ + if((ret_value=H5Aregister_atom(H5_TEMPLATE, (const VOIDP)new_template))==FAIL) + HGOTO_ERROR(H5E_ATOM, H5E_CANTREGISTER, FAIL); + +done: + if(ret_value == FAIL) + { /* Error condition cleanup */ + + } /* end if */ + + /* Normal function cleanup */ + + FUNC_LEAVE(H5C_mask, ID_H5C_copy, ret_value); +} /* end H5C_copy() */ + diff --git a/src/H5Cprivate.h b/src/H5Cprivate.h new file mode 100644 index 0000000..4f7357f --- /dev/null +++ b/src/H5Cprivate.h @@ -0,0 +1,25 @@ +/**************************************************************************** + * NCSA HDF * + * Software Development Group * + * National Center for Supercomputing Applications * + * University of Illinois at Urbana-Champaign * + * 605 E. Springfield, Champaign IL 61820 * + * * + * For conditions of distribution and use, see the accompanying * + * hdf/COPYING file. * + * * + ****************************************************************************/ + +/* $Id$ */ + +/* + * This file contains private information about the H5C module + */ + +#ifndef H5CPRIVATE_H +#define H5CPRIVATE_H + +#include "H5Cproto.h" + +#endif /* H5CPRIVATE_H */ + diff --git a/src/H5Cproto.h b/src/H5Cproto.h new file mode 100644 index 0000000..0d8f26d --- /dev/null +++ b/src/H5Cproto.h @@ -0,0 +1,41 @@ +/**************************************************************************** + * NCSA HDF * + * Software Development Group * + * National Center for Supercomputing Applications * + * University of Illinois at Urbana-Champaign * + * 605 E. Springfield, Champaign IL 61820 * + * * + * For conditions of distribution and use, see the accompanying * + * hdf/COPYING file. * + * * + ****************************************************************************/ + +/* $Id$ */ + +/* + * This file contains function prototypes for each exported function in the H5C module + */ + +#ifndef H5CPROTO_H +#define H5CPROTO_H + +#if defined c_plusplus || defined __cplusplus +extern "C" +{ +#endif /* c_plusplus || __cplusplus */ + +/* Functions in H5C.c */ +hatom_t H5C_create(hatom_t owner_id, hobjtype_t type, const char *name); +hatom_t H5C_copy(hatom_t tid); +herr_t H5C_release(hatom_t oid); +hatom_t H5C_get_default_atom(hobjtype_t type); +herr_t H5C_init(hatom_t dst_atm, const file_create_temp_t *src); +herr_t H5Cgetparm(hatom_t tid, file_create_param_t parm, VOIDP buf); +herr_t H5Csetparm(hatom_t tid, file_create_param_t parm, const VOIDP buf); + +#if defined c_plusplus || defined __cplusplus +} +#endif /* c_plusplus || __cplusplus */ + +#endif /* H5CPROTO_H */ + diff --git a/src/H5E.c b/src/H5E.c new file mode 100644 index 0000000..a697f39 --- /dev/null +++ b/src/H5E.c @@ -0,0 +1,394 @@ +/**************************************************************************** +* NCSA HDF * +* Software Development Group * +* National Center for Supercomputing Applications * +* University of Illinois at Urbana-Champaign * +* 605 E. Springfield, Champaign IL 61820 * +* * +* For conditions of distribution and use, see the accompanying * +* hdf/COPYING file. * +* * +****************************************************************************/ + +#ifdef RCSID +static char RcsId[] = "@(#)$Revision$"; +#endif + +/* $Id$ */ + +/*LINTLIBRARY */ +/*+ + FILE + hdf5err.c + HDF error reporting routines + + EXPORTED ROUTINES + H5Enew_err_stack -- Create a new error stack to push values on + H5Epush -- Push an error value on an error stack + + LIBRARY-SCOPED ROUTINES + + LOCAL ROUTINES + H5E_init_interface -- initialize the H5E interface + + */ + +#define HDF5_ERR_MASTER +#include "hdf5.h" +#include "H5Eprivate.h" /* Private error routines */ +#undef HDF5_ERR_MASTER + +#include "H5private.h" /* Generic Functions */ + +/*--------------------- Locally scoped variables -----------------------------*/ + +/* Whether we've installed the library termination function yet for this interface */ +static intn interface_initialize = FALSE; + +/*------------------_-- Local function prototypes ----------------------------*/ +static herr_t H5E_init_interface(void); + +/*-------------------------------------------------------------------------- +NAME + H5E_init_interface -- Initialize interface-specific information +USAGE + herr_t H5E_init_interface() + +RETURNS + SUCCEED/FAIL +DESCRIPTION + Initializes any interface-specific data or routines. + +--------------------------------------------------------------------------*/ +static herr_t H5E_init_interface(void) +{ +#ifdef LATER + CONSTR(FUNC, "H5E_init_interface"); /* For HERROR */ +#endif /* LATER */ + herr_t ret_value = SUCCEED; + + /* Don't use "FUNC_ENTER" macro, to avoid potential infinite recursion */ + PABLO_TRACE_ON(H5_mask, ID_H5Iinit_interface); + + /* Don't call this routine again... */ + interface_initialize = TRUE; + + /* Initialize the atom group for the error stacks */ + ret_value=H5Ainit_group(H5_ERR,HDF5_ERRSTACK_HASHSIZE,0); + + FUNC_LEAVE(H5_mask, ID_H5E_init_interface, ret_value); +} /* H5E_init_interface */ + +/*-------------------------------------------------------------------------- +NAME + H5Enew_err_stack -- Create a new error stack +USAGE + int32 H5Enew_err_stack(initial_stack_size); + uintn initial_stack_size; IN: Starting size of the error stack + +RETURNS + The ID of the error stack created on success, FAIL on failure. + +DESCRIPTION + Dynamically creates a new error stack to push error values onto. + +--------------------------------------------------------------------------*/ +int32 H5Enew_err_stack(uintn initial_stack_size) +{ + CONSTR(FUNC, "H5Enew_err_stack"); /* For HERROR */ + H5E_errstack_t *new_stack=NULL; /* Pointer to the new error stack */ + int32 ret_value = FAIL; + + FUNC_ENTER(H5E_mask, ID_H5Enew_err_stack, H5E_init_interface,FAIL); + + /* Allocate the stack header */ + if((new_stack=HDmalloc(sizeof(H5E_errstack_t)))==NULL) + HGOTO_DONE(FAIL); + + /* Initialize the stack header */ + new_stack->stack_size=initial_stack_size; + new_stack->stack_top=0; + if((new_stack->err_stack=HDcalloc(initial_stack_size,sizeof(H5E_error_t)))==NULL) + { + HDfree(new_stack); + HGOTO_DONE(FAIL); + } /* end if */ + new_stack->push=H5E_store; /* Set the default error handler */ + + /* Get an atom for the error stack */ + ret_value=H5Aregister_atom(H5_ERR, new_stack); + +done: + if(ret_value == FAIL) + { /* Error condition cleanup */ + + } /* end if */ + + /* Normal function cleanup */ + + FUNC_LEAVE(H5E_mask, ID_H5Enew_err_stack, ret_value); +} /* H5Enew_err_stack */ + +/*-------------------------------------------------------------------------- +NAME + H5Edelete_err_stack -- Destroy an error stack +USAGE + intn H5Edelete_err_stack(err_stack); + int32 err_stack; IN: Error stack to delete + +RETURNS + SUCCEED/FAIL + +DESCRIPTION + Destroys an error stack, releasing memory allocated, etc. + +--------------------------------------------------------------------------*/ +intn H5Edelete_err_stack(int32 err_stack) +{ + CONSTR(FUNC, "H5Edelete_err_stack"); /* For HERROR */ + H5E_errstack_t *old_stack=NULL; /* Pointer to the new error stack */ + intn ret_value = SUCCEED; + + FUNC_ENTER(H5E_mask, ID_H5Edelete_err_stack, H5E_init_interface,FAIL); + + /* Clear errors and check args and all the boring stuff. */ + if (H5Aatom_group(err_stack)!=H5_ERR) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL); + + /* Get the error stack to put the error on */ + if((old_stack=H5Aremove_atom(err_stack))==NULL) + HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL); + + /* Clear the error descriptions and reset the stack top */ + for(; old_stack->stack_top>0; old_stack->stack_top--) + { + if (old_stack->err_stack[old_stack->stack_top-1].desc) + { + HDfree(old_stack->err_stack[old_stack->stack_top-1].desc); + old_stack->err_stack[old_stack->stack_top-1].desc=NULL; + } /* end if */ + } /* end if */ + + HDfree(old_stack->err_stack); + HDfree(old_stack); + +done: + if(ret_value == FAIL) + { /* Error condition cleanup */ + + } /* end if */ + + /* Normal function cleanup */ + + FUNC_LEAVE(H5E_mask, ID_H5Edelete_err_stack, ret_value); +} /* H5Edelete_err_stack */ + +/*-------------------------------------------------------------------------- +NAME + H5Eclear -- Clear an error stack for later error entries +USAGE + void H5Eclear(int32 err_hand) + int32 err_hand; IN: The ID of the error stack to push the error onto. + +RETURNS + none +DESCRIPTION + Clear an error stack to allow errors to be pushed onto it. + +--------------------------------------------------------------------------*/ +void H5Eclear(int32 err_hand) +{ + CONSTR(FUNC, "H5Eclear"); /* For HERROR */ + H5E_errstack_t *err_stack=NULL; /* Pointer to the error stack to put value on */ + herr_t ret_value = SUCCEED; + + FUNC_ENTER(H5E_mask, ID_H5Eclear, H5E_init_interface,FAIL); + + /* Get the error stack for this error handler, initialized earlier in H5Enew_err_stack */ + if (H5Aatom_group(err_hand)!=H5_ERR) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL); + + /* Get the error stack to put the error on */ + if((err_stack=H5Aatom_object(err_hand))==NULL) + HGOTO_ERROR(H5E_BADATOM, H5E_BADATOM, FAIL); + + /* Clear the error descriptions and reset the stack top */ + for(; err_stack->stack_top>0; err_stack->stack_top--) + { + if (err_stack->err_stack[err_stack->stack_top-1].desc) + { + HDfree(err_stack->err_stack[err_stack->stack_top-1].desc); + err_stack->err_stack[err_stack->stack_top-1].desc=NULL; + } /* end if */ + } /* end if */ + +done: + if(ret_value == FAIL) + { /* Error condition cleanup */ + + } /* end if */ + + /* Normal function cleanup */ + + PABLO_TRACE_OFF(H5E_mask, ID_H5Eclear); /* ignore ret_value set */ +} /* H5Eclear */ + +/*-------------------------------------------------------------------------- +NAME + H5E_store -- Push an error value on an error stack +USAGE + void H5E_store(hdf_err_code_t err, const char *function_name, const char *file_name, intn line) + hdf_err_code_t err; IN: The error code which occurred. + const char *function_name; IN: Name of the function the error occurred within. + const char *file_name; IN: Name of the file the error occurred within. + intn line; IN: Line # in the file the error occurred on. + +RETURNS + none +DESCRIPTION + Pushes an error onto an error stack for this thread. (This is the default + action when errors occur, but can be overridden by user's code) + +--------------------------------------------------------------------------*/ +void H5E_store(int32 errid, hdf_maj_err_code_t maj, hdf_min_err_code_t min, const char *function_name, const char *file_name, intn line) +{ + CONSTR(FUNC, "H5E_store"); /* For HERROR */ + H5E_errstack_t *err_stack=NULL; /* Pointer to the error stack to put value on */ + herr_t ret_value = SUCCEED; + + FUNC_ENTER(H5E_mask, ID_H5E_store, H5E_init_interface,FAIL); + + /* Clear errors and check args and all the boring stuff. */ + H5Eclear(errid); + + /* Get the error stack to put the error on */ + if((err_stack=H5Aatom_object(errid))==NULL) + HGOTO_ERROR(H5E_BADATOM, H5E_BADATOM, FAIL); + + /* Check if we need to expand the stack */ + if(err_stack->stack_top>=err_stack->stack_size) + { + H5E_error_t *old_stack=err_stack->err_stack; /* in case realloc fails */ + + /* Ask for new stack that's twice as large */ + if((err_stack->err_stack=HDrealloc(old_stack,2*err_stack->stack_size))==NULL) + { + err_stack->err_stack=old_stack; + HGOTO_DONE(FAIL); + } /* end if */ + err_stack->stack_size *= 2; /* increase the size of the stack */ + } /* end if */ + + /* Push the error onto the error stack */ + err_stack->err_stack[err_stack->stack_top].maj=maj; + err_stack->err_stack[err_stack->stack_top].min=min; + HDstrncpy(err_stack->err_stack[err_stack->stack_top].function_name,function_name,MAX_FUNC_NAME_LEN); + err_stack->err_stack[err_stack->stack_top].file_name=file_name; + err_stack->err_stack[err_stack->stack_top].line=line; + + /* Increment the top of the error stack */ + err_stack->stack_top++; + +done: + if(ret_value == FAIL) + { /* Error condition cleanup */ + + } /* end if */ + + /* Normal function cleanup */ + + PABLO_TRACE_OFF(H5E_mask, ID_H5E_store); /* ignore ret_value set */ +} /* H5E_store */ + +/*-------------------------------------------------------------------------- +NAME + H5Epush -- Push an error value on an error stack +USAGE + void H5Epush(hdf_err_code_t err, const char *function_name, const char *file_name, intn line) + hdf_err_code_t err; IN: The error code which occurred. + const char *function_name; IN: Name of the function the error occurred within. + const char *file_name; IN: Name of the file the error occurred within. + intn line; IN: Line # in the file the error occurred on. + +RETURNS + none +DESCRIPTION + Pushes an error onto an error stack for this thread. + +--------------------------------------------------------------------------*/ +void H5Epush(hdf_maj_err_code_t maj, hdf_min_err_code_t min, const char *function_name, const char *file_name, intn line) +{ + CONSTR(FUNC, "H5Epush"); /* For HERROR */ + H5E_errstack_t *err_stack=NULL; /* Pointer to the error stack to put value on */ + herr_t ret_value = SUCCEED; + + FUNC_ENTER(H5E_mask, ID_H5Epush, H5E_init_interface,FAIL); + + /* Clear errors and check args and all the boring stuff. */ + H5ECLEAR; + if (function_name==NULL || file_name==NULL || H5Aatom_group(thrderrid)!=H5_ERR) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL); + + /* Get the error stack to put the error on */ + if((err_stack=H5Aatom_object(thrderrid))==NULL) + HGOTO_ERROR(H5E_BADATOM, H5E_BADATOM, FAIL); + + err_stack->push(thrderrid, maj, min, function_name, file_name, line); + +done: + if(ret_value == FAIL) + { /* Error condition cleanup */ + + } /* end if */ + + /* Normal function cleanup */ + + PABLO_TRACE_OFF(H5E_mask, ID_H5Epush); /* ignore ret_value set */ +} /* H5Epush */ + +/*-------------------------------------------------------------------------- +NAME + H5Eset_push -- Set the function to call when an error value is reported +USAGE + H5E_push_func_t H5Eset_push(H5E_push_func_t func) + H5E_push_func_t func; IN: New function to call when an error occurs. + +RETURNS + The function pointer to the previous error function on success, NULL on + failure. +DESCRIPTION + Changes the function which is called for errors on this thread. The thread + ID is implicit, ie. this function must be called within each thread whose + error function is to be changed. + +--------------------------------------------------------------------------*/ +H5E_push_func_t H5Eset_push(H5E_push_func_t func) +{ + CONSTR(FUNC, "H5Eset_push"); /* For HERROR */ + H5E_errstack_t *err_stack=NULL; /* Pointer to the error stack to put value on */ + H5E_push_func_t ret_value = NULL; + + FUNC_ENTER(H5E_mask, ID_H5Eset_push, H5E_init_interface,NULL); + + /* Clear errors and check args and all the boring stuff. */ + H5ECLEAR; + if (func==NULL) + HGOTO_ERROR(H5E_ARGS, H5E_BADRANGE, NULL); + + /* Get the error stack to put the error on */ + if((err_stack=H5Aatom_object(thrderrid))==NULL) + HGOTO_ERROR(H5E_BADATOM, H5E_BADATOM, NULL); + + ret_value=err_stack->push; + err_stack->push=func; + +done: + if(ret_value == NULL) + { /* Error condition cleanup */ + + } /* end if */ + + /* Normal function cleanup */ + + FUNC_LEAVE(H5E_mask, ID_H5Eset_push, ret_value); +} /* H5Eset_push */ + diff --git a/src/H5Eprivate.h b/src/H5Eprivate.h new file mode 100644 index 0000000..9de9d69 --- /dev/null +++ b/src/H5Eprivate.h @@ -0,0 +1,131 @@ +/**************************************************************************** + * NCSA HDF * + * Software Development Group * + * National Center for Supercomputing Applications * + * University of Illinois at Urbana-Champaign * + * 605 E. Springfield, Champaign IL 61820 * + * * + * For conditions of distribution and use, see the accompanying * + * hdf/COPYING file. * + * * + ****************************************************************************/ + +/* $Id$ */ + +/* + * Header file for error values, etc. + */ + +#ifndef HDF5ERR_H +#define HDF5ERR_H + +#include "H5Eproto.h" + +/* + ====================================================================== + Error codes + + NOTE: Remember to update the error_messages[] structure later in this file + whenever errors are added/deleted from this list. + ====================================================================== + */ +/* + * This section of code is designed to be only accessible to the actual + * error-management code. + */ +#ifdef HDF5_ERR_MASTER + +/* + * error_messages is the list of error messages in the system, kept as + * error_code-message pairs. + */ + +typedef struct + { + hdf_maj_err_code_t error_code; + const char *str; + } +hdf_maj_error_messages_t; + +static const hdf_maj_error_messages_t hdf_maj_error_messages[] = +{ + {H5E_NONE_MAJOR, "No error"}, + {H5E_ARGS, "Invalid arguments to routine"}, + {H5E_RESOURCE, "Resource unavailable"}, + {H5E_INTERNAL, "Internal HDF5 error (too specific to document in detail)"}, + {H5E_FILE, "File Accessability"}, + {H5E_IO, "Low-level I/O"}, + {H5E_FUNC, "Function Entry/Exit"}, + {H5E_ATOM, "Object Atom"}, +}; + +typedef struct + { + hdf_min_err_code_t error_code; + const char *str; + } +hdf_min_error_messages_t; + +static const hdf_min_error_messages_t hdf_min_error_messages[] = +{ + {H5E_NONE_MINOR, "No error"}, + {H5E_UNINITIALIZED, "Information is uninitialized"}, + {H5E_UNSUPPORTED, "Feature is unsupported"}, + {H5E_BADTYPE, "Incorrect type found"}, + {H5E_BADRANGE, "Incorrect range of argument"}, + {H5E_NOSPACE, "No space available for allocation"}, + {H5E_FILEEXISTS, "File already exists"}, + {H5E_FILEOPEN, "File already open"}, + {H5E_CANTCREATE, "Can't create file"}, + {H5E_CANTOPEN, "Can't open file"}, + {H5E_NOTHDF5, "Not an HDF5 format file"}, + {H5E_BADFILE, "Bad file ID accessed"}, + {H5E_SEEKERROR, "File seek failed"}, + {H5E_READERROR, "File read failed"}, + {H5E_WRITEERROR, "File write failed"}, + {H5E_CANTINIT, "Can't initialize interface"}, + {H5E_ALREADYINIT, "Object already initialized"}, + {H5E_BADATOM, "Can't find atom information"}, + {H5E_CANTREGISTER, "Can't register new atom"} +}; + +/* We use a stack to hold the errors plus we keep track of the function, + file and line where the error occurs. */ + +/* the structure of the error stack element */ +typedef struct error_t + { + hdf_maj_err_code_t maj; /* Major error number */ + hdf_min_err_code_t min; /* Minor error number */ + char function_name[MAX_FUNC_NAME_LEN]; /* function where error occur */ + const char *file_name; /* file where error occur */ + intn line; /* line in file where error occurs */ + char *desc; /* optional supplied description */ + } +H5E_error_t; + +/* Structure to store error information for a thread */ +typedef struct errstack_t + { + uintn stack_size; /* Number of elements allocated in the stack */ + uintn stack_top; /* Offset of the next open stack element */ + H5E_error_t *err_stack; /* Pointer to the error stack */ + H5E_push_func_t push; /* Function to call when an error is to be reported */ + } H5E_errstack_t; + +#endif /* HDF5_ERR_MASTER */ + +#if defined c_plusplus || defined __cplusplus +extern "C" +{ +#endif /* c_plusplus || __cplusplus */ + +/* Private functions in H5E.c */ +void H5E_store(int32 errid, hdf_maj_err_code_t maj, hdf_min_err_code_t min, const char *function_name, const char *file_name, intn line); + +#if defined c_plusplus || defined __cplusplus +} +#endif /* c_plusplus || __cplusplus */ + +#endif /* HDF5ERR_H */ + diff --git a/src/H5Eproto.h b/src/H5Eproto.h new file mode 100644 index 0000000..da011bf --- /dev/null +++ b/src/H5Eproto.h @@ -0,0 +1,126 @@ +/**************************************************************************** + * NCSA HDF * + * Software Development Group * + * National Center for Supercomputing Applications * + * University of Illinois at Urbana-Champaign * + * 605 E. Springfield, Champaign IL 61820 * + * * + * For conditions of distribution and use, see the accompanying * + * hdf/COPYING file. * + * * + ****************************************************************************/ + +/* $Id$ */ + +/* + * This file contains function prototypes for each exported function in the H5E module + */ + +#ifndef H5EPROTO_H +#define H5EPROTO_H + +/* HERROR macro, used to facilitate error reporting. Assumes that + there's a variable called FUNC which holds the function name. + Assume that func and file are both stored in static space, or at + least be not corrupted in the meanwhile. */ + +#define HERROR(maj, min) H5Epush(maj, min, FUNC, __FILE__, __LINE__) + +/* HRETURN_ERROR macro, used to facilitate error reporting. Makes + same assumptions as HERROR. IN ADDITION, this macro causes + a return from the calling routine */ + +#define HRETURN_ERROR(maj, min, ret_val) {HERROR(maj, min); return(ret_val);} + +/* HGOTO_ERROR macro, used to facilitate error reporting. Makes + same assumptions as HERROR. IN ADDITION, this macro causes + a jump to the label 'done' which should be in every fucntion + Also there is an assumption of a variable 'ret_value' */ + +#define HGOTO_ERROR(maj, min, ret_val) { HERROR(maj, min); \ + ret_value = ret_val; goto done; } + +/* HGOTO_DONE macro, used to facilitate the new error reporting model. + This macro is just a wrapper to set the return value and jump to the 'done' + label. Also assumption of a variable 'ret_value' */ + +#define HGOTO_DONE(ret_val) {ret_value = ret_val; goto done;} + +/* H5ECLEAR macro, used to facilitate the new error reporting model. + This macro is just a wrapper to clear the error stack with the thread + error ID */ + +#define H5ECLEAR H5Eclear(thrderrid) + +/* Declare an enumerated type which holds all the valid major HDF error codes */ +typedef enum + { + H5E_NONE_MAJOR = 0, /* special zero, no error */ + H5E_ARGS, /* Invalid arguments to routine */ + H5E_RESOURCE, /* Resource unavailable */ + H5E_INTERNAL, /* Internal error (too specific to document in detail) */ + H5E_FILE, /* File Accessability */ + H5E_IO, /* Low-level I/O */ + H5E_FUNC, /* Function Entry/Exit */ + H5E_ATOM /* Object Atom */ + } +hdf_maj_err_code_t; + +/* Declare an enumerated type which holds all the valid minor HDF error codes */ +typedef enum + { + H5E_NONE_MINOR = 0, /* special zero, no error */ + + /* Argument errors */ + H5E_UNINITIALIZED, /* Information is unitialized */ + H5E_UNSUPPORTED, /* Feature is unsupported */ + H5E_BADTYPE, /* Incorrect type found */ + H5E_BADRANGE, /* Incorrect range of argument */ + + /* Resource errors */ + H5E_NOSPACE, /* No space available for allocation */ + + /* File accessability errors */ + H5E_FILEEXISTS, /* File already exists */ + H5E_FILEOPEN, /* File already open */ + H5E_CANTCREATE, /* Can't create file */ + H5E_CANTOPEN, /* Can't open file */ + H5E_NOTHDF5, /* Not an HDF5 format file */ + H5E_BADFILE, /* Bad file ID accessed */ + + /* Generic low-level file I/O errors */ + H5E_SEEKERROR, /* File seek failed */ + H5E_READERROR, /* File read failed */ + H5E_WRITEERROR, /* File write failed */ + + /* Function entry/exit interface errors */ + H5E_CANTINIT, /* Can't initialize interface */ + H5E_ALREADYINIT, /* Object already initialized */ + + /* Object atom related errors */ + H5E_BADATOM, /* Can't find atom information */ + H5E_CANTREGISTER /* Can't register new atom */ + } +hdf_min_err_code_t; + +/* Function pointer to report errors through */ +typedef void (*H5E_push_func_t)(int32 errid, hdf_maj_err_code_t maj, hdf_min_err_code_t min, const char *function_name, const char *file_name, intn line); + +#if defined c_plusplus || defined __cplusplus +extern "C" +{ +#endif /* c_plusplus || __cplusplus */ + +/* Functions in H5E.c */ +int32 H5Enew_err_stack(uintn initial_stack_size); +intn H5Edelete_err_stack(int32 err_hand); +H5E_push_func_t H5Eset_push(H5E_push_func_t func); +void H5Epush(hdf_maj_err_code_t maj, hdf_min_err_code_t min, const char *function_name, const char *file_name, intn line); +void H5Eclear(int32 err_hand); + +#if defined c_plusplus || defined __cplusplus +} +#endif /* c_plusplus || __cplusplus */ + +#endif /* H5EPROTO_H */ + diff --git a/src/H5F.c b/src/H5F.c new file mode 100644 index 0000000..d75e09f --- /dev/null +++ b/src/H5F.c @@ -0,0 +1,852 @@ +/**************************************************************************** +* NCSA HDF * +* Software Development Group * +* National Center for Supercomputing Applications * +* University of Illinois at Urbana-Champaign * +* 605 E. Springfield, Champaign IL 61820 * +* * +* For conditions of distribution and use, see the accompanying * +* hdf/COPYING file. * +* * +****************************************************************************/ + +#ifdef RCSID +static char RcsId[] = "@(#)$Revision$"; +#endif + +/* $Id$ */ + +/*LINTLIBRARY */ +/* + FILE + hdf5file.c + HDF5 file I/O routines + + EXPORTED ROUTINES + H5Fcreate -- Create an HDF5 file + H5Fclose -- Close an open HDF5 file + + LIBRARY-SCOPED ROUTINES + + LOCAL ROUTINES + H5F_init_interface -- initialize the H5F interface + */ + +#define HDF5_FILE_MASTER +#include "hdf5.h" +#undef HDF5_FILE_MASTER + +/* Packages needed by this file... */ +#include "H5private.h" /*library functions */ +#include "H5ACprivate.h" /*cache */ +#include "H5Gprivate.h" /*symbol tables */ +#include "H5MMprivate.h" /*core memory management */ + +/*--------------------- Locally scoped variables -----------------------------*/ + +/* Whether we've installed the library termination function yet for this interface */ +static intn interface_initialize = FALSE; + +/*--------------------- Local function prototypes ----------------------------*/ +static herr_t H5F_init_interface(void); +static hdf5_file_t *H5F_new (void); +static hdf5_file_t *H5F_dest (hdf5_file_t *f); + +/*-------------------------------------------------------------------------- +NAME + H5F_init_interface -- Initialize interface-specific information +USAGE + herr_t H5F_init_interface() + +RETURNS + SUCCEED/FAIL +DESCRIPTION + Initializes any interface-specific data or routines. + +--------------------------------------------------------------------------*/ +static herr_t H5F_init_interface(void) +{ +#ifdef LATER + CONSTR(FUNC, "H5F_init_interface"); /* For HERROR */ +#endif /* LATER */ + herr_t ret_value = SUCCEED; + + /* Don't use "FUNC_ENTER" macro, to avoid potential infinite recursion */ + PABLO_TRACE_ON(H5F_mask, ID_H5F_init_interface); + + /* Don't call this routine again... */ + interface_initialize = TRUE; + + /* Initialize the atom group for the file IDs */ + ret_value=H5Ainit_group(H5_FILE,HDF5_FILEID_HASHSIZE,0); + + FUNC_LEAVE(H5_mask, ID_H5F_init_interface, ret_value); +} /* H5F_init_interface */ + +#ifdef LATER +/*-------------------------------------------------------------------------- + NAME + H5F_encode_length_unusual -- encode an unusual length size + USAGE + void H5F_encode_length_unusual(f, p, l) + const hdf5_file_t *f; IN: pointer to the file record + uint8 **p; IN: pointer to buffer pointer to encode length in + uint8 *l; IN: pointer to length to encode + RETURNS + none + DESCRIPTION + Encode non-standard (i.e. not 2, 4 or 8-byte) lengths in file meta-data. +--------------------------------------------------------------------------*/ +void H5F_encode_length_unusual(const hdf5_file_t *f, uint8 **p, uint8 *l) +{ +#ifdef LATER + CONSTR(FUNC, "H5F_encode_length_unusual"); +#endif /* LATER */ + intn i=f->file_create_parms.length_size; + +/* For non-little-endian platforms, encode each byte in memory backwards */ +#if ((DF_MT&0xFFF0)!=0x4440) + for(; i>=0; i--,(*p)++) + *(*p)=*(l+i); +#else /* platform has little-endian integers */ + for(; i>=0; i--,(*p)++) + *(*p)=*l; +#endif + +#ifdef LATER +done: + if(ret_value == FALSE) + { /* Error condition cleanup */ + + } /* end if */ +#endif /* LATER */ + + /* Normal function cleanup */ + +} /* H5F_encode_length_unusual */ + +/*-------------------------------------------------------------------------- + NAME + H5F_encode_offset_unusual -- encode an unusual offset size + USAGE + void H5F_encode_offset_unusual(f, p, o) + const hdf5_file_t *f; IN: pointer to the file record + uint8 **p; IN: pointer to buffer pointer to encode offset in + uint8 *o; IN: pointer to offset to encode + RETURNS + none + DESCRIPTION + Encode non-standard (i.e. not 2, 4 or 8-byte) offsets in file meta-data. +--------------------------------------------------------------------------*/ +void H5F_encode_offset_unusual(const hdf5_file_t *f, uint8 **p, uint8 *o) +{ +#ifdef LATER + CONSTR(FUNC, "H5F_encode_offset_unusual"); +#endif /* LATER */ + intn i=f->file_create_parms.offset_size; + +/* For non-little-endian platforms, encode each byte in memory backwards */ +#if ((DF_MT&0xFFF0)!=0x4440) + for(; i>=0; i--,(*p)++) + *(*p)=*(o+i); +#else /* platform has little-endian integers */ + for(; i>=0; i--,(*p)++) + *(*p)=*o; +#endif + +#ifdef LATER +done: + if(ret_value == FALSE) + { /* Error condition cleanup */ + + } /* end if */ +#endif /* LATER */ + + /* Normal function cleanup */ + +} /* H5F_encode_offset_unusual */ +#endif /* LATER */ + +/*-------------------------------------------------------------------------- + NAME + H5F_compare_filename -- compare file objects for the atom API + USAGE + intn HPcompare_filename(obj, key) + const VOIDP obj; IN: pointer to the file record + const VOIDP key; IN: pointer to the name of file + RETURNS + TRUE if the key matches the obj, FALSE otherwise + DESCRIPTION + Look inside the file record for the atom API and compare the the + filenames. +--------------------------------------------------------------------------*/ +intn H5F_compare_filename(const VOIDP obj, const VOIDP key) +{ +#ifdef LATER + CONSTR(FUNC, "H5F_compare_filename"); +#endif /* LATER */ + + +#ifdef LATER +done: + if(ret_value == FALSE) + { /* Error condition cleanup */ + + } /* end if */ +#endif /* LATER */ + + /* Normal function cleanup */ + + return(!HDstrcmp(((const hdf5_file_t *)obj)->filename,(const char *)key)); +} /* H5F_compare_filename */ + +/*-------------------------------------------------------------------------- + NAME + H5Fget_create_template + PURPOSE + Get an atom for a copy of the file-creation template for this file + USAGE + hatom_t H5Fget_create_template(fid) + hatom_t fid; IN: File ID + RETURNS + Returns template ID on success, FAIL on failure + DESCRIPTION + This function returns an atom with a copy of the template parameters + used to create a file. +--------------------------------------------------------------------------*/ +hatom_t H5Fget_create_template(hatom_t fid) +{ + CONSTR(FUNC, "H5Fget_create_template"); /* for HERROR */ + hdf5_file_t *file=NULL; /* file struct for file to close */ + hatom_t ret_value = FAIL; + + FUNC_ENTER(H5F_mask, ID_H5Fget_create_template, H5F_init_interface, FAIL); + + /* Clear errors and check args and all the boring stuff. */ + H5ECLEAR; + + /* Get the file structure */ + if((file=H5Aatom_object(fid))==NULL) + HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL); + + /* Create the template object to return */ + if((ret_value=H5Mcreate(fid,H5_TEMPLATE,NULL))==FAIL) + HGOTO_ERROR(H5E_FUNC, H5E_CANTCREATE, FAIL); + + if(H5C_init(ret_value,&(file->file_create_parms))==FAIL) + HGOTO_ERROR(H5E_FUNC, H5E_CANTINIT, FAIL); + +done: + if(ret_value == FAIL) + { /* Error condition cleanup */ + + } /* end if */ + + /* Normal function cleanup */ + + FUNC_LEAVE(H5F_mask, ID_H5Fget_create_template, ret_value); +} /* end H5Fget_create_template() */ + +/*-------------------------------------------------------------------------- + NAME + H5Fis_hdf5 + PURPOSE + Check the file signature to detect an HDF5 file. + USAGE + hbool_t H5Fis_hdf5(filename) + const char *filename; IN: Name of the file to check + RETURNS + TRUE/FALSE/FAIL + DESCRIPTION + This function determines if a file is an HDF5 format file. +--------------------------------------------------------------------------*/ +hbool_t H5Fis_hdf5(const char *filename) +{ + CONSTR(FUNC, "H5Fis_hdf5"); /* for HERROR */ + hdf_file_t f_handle=H5FI_INVALID_FILE; /* file handle */ + uint8 temp_buf[HDF5_FILE_SIGNATURE_LEN]; /* temporary buffer for checking file signature */ + size_t curr_off=0; /* The current offset to check in the file */ + size_t file_len=0; /* The length of the file we are checking */ + hbool_t ret_value = BFALSE; + + FUNC_ENTER(H5F_mask, ID_H5Fis_hdf5, H5F_init_interface, BFAIL); + + /* Clear errors and check args and all the boring stuff. */ + H5ECLEAR; + if(filename==NULL) + HGOTO_ERROR(H5E_ARGS, H5E_BADRANGE, BFAIL); + + /* Open the file */ + f_handle=H5FI_OPEN(filename,0); + if(H5FI_OPENERR(f_handle)) + HGOTO_ERROR(H5E_FILE, H5E_BADFILE, BFAIL); + + /* Get the length of the file */ + if(H5FI_SEEKEND(f_handle)==FAIL) + HGOTO_ERROR(H5E_IO, H5E_SEEKERROR, BFAIL); + file_len=H5FI_TELL(f_handle); + + /* Check the offsets where the file signature is possible */ + while(curr_off<file_len) + { + if(H5FI_SEEK(f_handle,curr_off)==FAIL) + HGOTO_ERROR(H5E_IO, H5E_READERROR, BFAIL); + if(H5FI_READ(f_handle,temp_buf, HDF5_FILE_SIGNATURE_LEN)==FAIL) + HGOTO_ERROR(H5E_IO, H5E_READERROR, BFAIL); + if(HDmemcmp(temp_buf,HDF5_FILE_SIGNATURE,HDF5_FILE_SIGNATURE_LEN)==0) + { + ret_value=BTRUE; + break; + } /* end if */ + if(curr_off==0) + curr_off=512; + else + curr_off*=2; + } /* end while */ + H5FI_CLOSE(f_handle); /* close the file we opened */ + +done: + if(ret_value == BFAIL) + { /* Error condition cleanup */ + + /* Check if we left a dangling file handle */ + if(f_handle!=H5FI_INVALID_FILE) + H5FI_CLOSE(f_handle); /* close the file we opened */ + + } /* end if */ + + /* Normal function cleanup */ + + FUNC_LEAVE(H5F_mask, ID_H5Fis_hdf5, ret_value); +} /* end H5Fis_hdf5() */ + + +/*------------------------------------------------------------------------- + * Function: H5F_new + * + * Purpose: Creates a new file object and initializes it. The + * H5Fopen and H5Fcreate functions then fill in various + * fields. + * + * Return: Success: Ptr to a new file struct. + * + * Failure: NULL + * + * Programmer: Robb Matzke + * robb@maya.nuance.com + * Jul 18 1997 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static hdf5_file_t * +H5F_new (void) +{ + hdf5_file_t *f = H5MM_xcalloc (1, sizeof(hdf5_file_t)); + + /* Create an error stack for errors with this file */ + f->file_err = H5Enew_err_stack(HDF5_FILE_ERRSTACK); + + /* Create a cache */ + H5AC_new (f); + + /* Create a root symbol slot */ + f->root_sym = H5MM_xcalloc (1, sizeof (H5G_entry_t)); + f->root_sym->type = H5G_NOTHING_CACHED; + + return f; +} + + +/*------------------------------------------------------------------------- + * Function: H5F_dest + * + * Purpose: Destroys a file structure. This function does not flush + * the cache or anything else; it only frees memory associated + * with the file struct. + * + * Return: Success: NULL + * + * Failure: NULL + * + * Programmer: Robb Matzke + * robb@maya.nuance.com + * Jul 18 1997 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static hdf5_file_t * +H5F_dest (hdf5_file_t *f) +{ + if (f) { + H5AC_dest (f); + if(f->file_err!=0) H5Edelete_err_stack (f->file_err); + f->dir = H5MM_xfree (f->dir); + f->filename = H5MM_xfree (f->filename); + H5MM_xfree (f); + } + return NULL; +} + +/*-------------------------------------------------------------------------- + NAME + H5Fcreate + PURPOSE + Create a new HDF5 file. + USAGE + int32 H5Fcreate(filename, flags) + const char *filename; IN: Name of the file to create + uintn flags; IN: Flags to indicate various options. + hatom_t create_temp; IN: File-creation template + hatom_t access_temp; IN: File-access template + RETURNS + Returns file ID on success, FAIL on failure + DESCRIPTION + This is the primary function for creating HDF5 files . The flags + parameter determines whether an existing file will be overwritten or not. + All newly created files are opened for both reading and writing. All flags + may be combined with the "||" (logical OR operator) to change the behavior + of the file open call. + The flags currently defined: + H5ACC_OVERWRITE - Truncate file, if it already exists. The file will + be truncated, erasing all data previously stored in the file. + The more complex behaviors of a file's creation and access are + controlled through the file-creation and file-access templates. + + MODIFICATIONS: + Robb Matzke, 18 Jul 1997 + File struct creation and destruction is through H5F_new() H5F_dest(). + Writing the root symbol table entry is done with H5G_encode(). +--------------------------------------------------------------------------*/ +hatom_t H5Fcreate(const char *filename, uintn flags, hatom_t create_temp, hatom_t access_temp) +{ + CONSTR(FUNC, "H5Fcreate"); /* for HERROR */ + hdf5_file_t *new_file=NULL; /* file struct for new file */ + hdf_file_t f_handle=H5FI_INVALID_FILE; /* file handle */ + const file_create_temp_t *f_create_parms; /* pointer to the parameters to use when creating the file */ + uint8 temp_buf[2048], *p; /* temporary buffer for encoding header */ + intn file_exists=0; /* flag to indicate that file exists already */ + hatom_t ret_value = FAIL; + + FUNC_ENTER(H5F_mask, ID_H5Fcreate, H5F_init_interface, FAIL); + + /* Clear errors and check args and all the boring stuff. */ + H5ECLEAR; + if(filename==NULL) + HGOTO_ERROR(H5E_ARGS, H5E_BADRANGE, FAIL); + + /* See if this file is already open */ + if(H5Asearch_atom(H5_FILE,H5F_compare_filename,(const VOIDP)filename)!=NULL) + HGOTO_ERROR(H5E_FILE, H5E_FILEOPEN, FAIL); + + /* Check if the file already exists */ + f_handle=H5FI_OPEN(filename,0); + if(!H5FI_OPENERR(f_handle)) + { + file_exists=1; /* set the flag to indicate that the file already exists */ + H5FI_CLOSE(f_handle); /* close the file we opened */ + f_handle=H5FI_INVALID_FILE; + } /* end if */ + + /* throw an error if the file exists and we aren't allowed to overwrite it */ + if((flags&H5ACC_OVERWRITE)==0 && file_exists) + HGOTO_ERROR(H5E_FILE, H5E_FILEEXISTS, FAIL); + + /* OK to create/overwrite the file */ + f_handle=H5FI_CREATE(filename); + if(H5FI_OPENERR(f_handle)) + HGOTO_ERROR(H5E_FILE, H5E_CANTCREATE, FAIL); + + /* Create the file node */ + if (NULL==(new_file=H5F_new())) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL); + + /* Set the non-zero elements of the file structure */ + new_file->dir=HDgetcwd(NULL,0); /* get the directory we just created the file within */ + new_file->filename=HDstrdup(filename); /* make a copy of the filename */ + new_file->acc_perm=H5ACC_WRITE; /* all new files we create have write permission */ + new_file->file_handle=f_handle; /* keep the file handle we just opened */ + new_file->ref_count=1; /* only 1 fid handed out so far */ + new_file->consist_flags=0x03; /* Set file-consistency flags: write-access and "file is consistent" */ + new_file->smallobj_off=0; /* Set the offset of the small-object heap */ + new_file->freespace_off=0; /* Set the offset of the free-space info */ + /* Get the file-creation template & record it */ + if(create_temp<=0) + create_temp=H5C_get_default_atom(H5_TEMPLATE); + if((f_create_parms=H5Aatom_object(create_temp))==NULL) + HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL); + HDmemcpy(&new_file->file_create_parms,f_create_parms,sizeof(file_create_temp_t)); + +#ifdef LATER + /* Get the file-access template & record it */ + if(access_temp<=0) + access_temp=H5CPget_default_atom(H5_TEMPLATE); + if((f_access_parms=H5Aatom_object(access_temp))==NULL) + HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL); + HDmemcpy(&new_file->file_access_parms,f_access_parms,sizeof(file_access_temp_t)); +#endif /* LATER */ + + /* Create the basic skeleton of the file */ + + /* Seek to the correct offset to write out the file signature & boot-block */ + if(new_file->file_create_parms.userblock_size>0) + if(H5FI_SEEK(new_file->file_handle,new_file->file_create_parms.userblock_size)==FAIL) + HGOTO_ERROR(H5E_IO, H5E_SEEKERROR, FAIL); + + /* Write out the file-signature */ + if(H5FI_WRITE(new_file->file_handle,HDF5_FILE_SIGNATURE,HDF5_FILE_SIGNATURE_LEN)==FAIL) + HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL); + + /* Encode the boot block */ + p=temp_buf; + *p++=f_create_parms->bootblock_ver; /* Encode Boot-block version # */ + *p++=f_create_parms->smallobject_ver; /* Encode Small-Object Heap version # */ + *p++=f_create_parms->freespace_ver; /* Encode Free-Space Info version # */ + *p++=f_create_parms->objectdir_ver; /* Encode Object Directory Format version # */ + *p++=f_create_parms->sharedheader_ver; /* Encode Shared-Header Info version # */ + *p++=(uint8)f_create_parms->offset_size; /* Encode the number of bytes for the offset */ + *p++=(uint8)f_create_parms->length_size; /* Encode the number of bytes for the length */ + *p++=0; /* Encode the reserved byte :-) */ + UINT32ENCODE(p,f_create_parms->btree_page_size); /* Encode the B-Tree page size */ + UINT32ENCODE(p,new_file->consist_flags); /* Encode File-Consistancy flags */ + H5F_encode_offset(new_file,p,new_file->smallobj_off); /* Encode offset of global small-object heap */ + H5F_encode_offset(new_file,p,new_file->freespace_off); /* Encode offset of global free-space heap */ + /* Predict the header length and encode it: */ + H5F_encode_length(new_file,p,(p-temp_buf)+f_create_parms->length_size+H5F_symbol_table_size(new_file)); /* Encode length of boot-block */ + + /* Encode the (bogus) symbol-table entry */ + if (H5G_encode (new_file, &p, new_file->root_sym)<0) { + HGOTO_ERROR (H5E_IO, H5E_WRITEERROR, FAIL); + } + + /* Write out the boot block */ + if(H5FI_WRITE(new_file->file_handle,temp_buf,(size_t)(p-temp_buf))==FAIL) + HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL); + new_file->logical_len = p - temp_buf; + + + /* Get an atom for the file */ + if((ret_value=H5Aregister_atom(H5_FILE, new_file))==FAIL) + HGOTO_ERROR(H5E_ATOM, H5E_CANTREGISTER, FAIL); + +done: + if(ret_value == FAIL) + { /* Error condition cleanup */ + + /* Check if we left a dangling file handle */ + if(f_handle!=H5FI_INVALID_FILE) + H5FI_CLOSE(f_handle); /* close the file we opened */ + + /* Check if we left a dangling file struct */ + if (new_file) H5F_dest (new_file); + } + + /* Normal function cleanup */ + + FUNC_LEAVE(H5F_mask, ID_H5Fcreate, ret_value); +} /* end H5Fcreate() */ + + +/*-------------------------------------------------------------------------- + NAME + H5Fopen + PURPOSE + Open an existing HDF5 file. + USAGE + hatom_t H5Fopen(filename, flags, access_temp) + const char *filename; IN: Name of the file to create + uintn flags; IN: Flags to indicate various options. + hatom_t access_temp; IN: File-access template + RETURNS + Returns file ID on success, FAIL on failure + DESCRIPTION + This is the primary function for accessing existing HDF5 files. The + flags parameter determines whether writing to an existing file will be allowed + or not. All flags may be combined with the "||" (logical OR operator) to + change the behavior of the file open call. + The flags currently defined: + H5ACC_WRITE - Allow writing to the file. + The more complex behaviors of a file's access are controlled through + the file-access template. + + MODIFICATIONS: + Robb Matzke, 18 Jul 1997 + File struct creation and destruction is through H5F_new() H5F_dest(). + Reading the root symbol table entry is done with H5G_decode(). +--------------------------------------------------------------------------*/ +hatom_t H5Fopen(const char *filename, uintn flags, hatom_t access_temp) +{ + CONSTR(FUNC, "H5Fopen"); /* for HERROR */ + hdf5_file_t *new_file=NULL; /* file struct for new file */ + hdf_file_t f_handle=H5FI_INVALID_FILE; /* file handle */ + hatom_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 */ + uint8 temp_buf[2048], *p; /* temporary buffer for encoding header */ + size_t curr_off=0; /* The current offset to check in the file */ + size_t file_len=0; /* The length of the file we are checking */ + hatom_t ret_value = FAIL; + + FUNC_ENTER(H5F_mask, ID_H5Fopen, H5F_init_interface, FAIL); + + /* Clear errors and check args and all the boring stuff. */ + H5ECLEAR; + if(filename==NULL) + HGOTO_ERROR(H5E_ARGS, H5E_BADRANGE, FAIL); + + /* See if this file is already open */ + new_file=H5Asearch_atom(H5_FILE,H5F_compare_filename,(const VOIDP)filename); + + /* If the file is already open, check the access permissions and go ahead with it */ + if(new_file!=NULL && new_file->acc_perm==flags) + { + /* Get an atom for the file */ + new_file->ref_count++; /* increment the reference count for the file */ + if((ret_value=H5Aregister_atom(H5_FILE, new_file))==FAIL) + HGOTO_ERROR(H5E_ATOM, H5E_CANTREGISTER, FAIL); + HGOTO_DONE(ret_value); + } /* end if */ + + /* + * If the file exists but has different permissions or if it's a new file, + * start a new file handle for it, etc. + */ + if(H5Fis_hdf5(filename)==BFALSE) + HGOTO_ERROR(H5E_FILE, H5E_NOTHDF5, FAIL); + + /* Check if the file already exists */ + f_handle=H5FI_OPEN(filename,flags); + if(H5FI_OPENERR(f_handle)) + HGOTO_ERROR(H5E_FILE, H5E_CANTOPEN, FAIL); + + /* Create the file node */ + if (NULL==(new_file=H5F_new())) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL); + + /* Set the non-zero elements of the file structure */ + new_file->dir=HDgetcwd(NULL,0); /* get the directory we just created the file within */ + new_file->filename=HDstrdup(filename); /* make a copy of the filename */ + new_file->acc_perm=flags; /* set the access permissions */ + new_file->file_handle=f_handle; /* keep the file handle we just opened */ + new_file->ref_count=1; /* only 1 fid handed out so far */ + create_temp=H5C_get_default_atom(H5_TEMPLATE); + if((f_create_parms=H5Aatom_object(create_temp))==NULL) + HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL); + HDmemcpy(&new_file->file_create_parms,f_create_parms,sizeof(file_create_temp_t)); + +#ifdef LATER + if(access_temp<=0) + access_temp=H5CPget_default_atom(H5_TEMPLATE); + if((f_access_parms=H5Aatom_object(access_temp))==NULL) + HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL); + HDmemcpy(&new_file->file_access_parms,f_access_parms,sizeof(file_access_temp_t)); +#endif /* LATER */ + + /* Read the basic skeleton of the file */ + + /* Seek to the correct offset to read in the file signature & boot-block */ + /* Get the length of the file */ + if(H5FI_SEEKEND(new_file->file_handle)==FAIL) + HGOTO_ERROR(H5E_IO, H5E_SEEKERROR, BFAIL); + file_len=H5FI_TELL(new_file->file_handle); + + /* Check the offsets where the file signature is possible */ + while(curr_off<file_len) + { + if(H5FI_SEEK(new_file->file_handle,curr_off)==FAIL) + HGOTO_ERROR(H5E_IO, H5E_READERROR, BFAIL); + if(H5FI_READ(new_file->file_handle,temp_buf, HDF5_FILE_SIGNATURE_LEN)==FAIL) + HGOTO_ERROR(H5E_IO, H5E_READERROR, BFAIL); + if(HDmemcmp(temp_buf,HDF5_FILE_SIGNATURE,HDF5_FILE_SIGNATURE_LEN)==0) + { + new_file->file_create_parms.userblock_size=curr_off; + break; + } /* end if */ + if(curr_off==0) + curr_off=512; + else + curr_off*=2; + } /* end while */ + if(curr_off>file_len) + HGOTO_ERROR(H5E_FILE, H5E_NOTHDF5, FAIL); + + /* Read in the fixed-size part of the boot-block */ + if(H5FI_READ(new_file->file_handle,temp_buf,16)==FAIL) + HGOTO_ERROR(H5E_IO, H5E_WRITEERROR, FAIL); + + /* Decode the boot block */ + p=temp_buf; + new_file->file_create_parms.bootblock_ver=*p++; /* Decode Boot-block version # */ + new_file->file_create_parms.smallobject_ver=*p++; /* Decode Small-Object Heap version # */ + new_file->file_create_parms.freespace_ver=*p++; /* Decode Free-Space Info version # */ + new_file->file_create_parms.objectdir_ver=*p++; /* Decode Object Directory Format version # */ + new_file->file_create_parms.sharedheader_ver=*p++; /* Decode Shared-Header Info version # */ + new_file->file_create_parms.offset_size=*p++; /* Decode the number of bytes for the offset */ + new_file->file_create_parms.length_size=*p++; /* Decode the number of bytes for the length */ + p++; /* Decode the reserved byte :-) */ + UINT32DECODE(p,new_file->file_create_parms.btree_page_size); /* Decode the B-Tree page size */ + UINT32DECODE(p,new_file->consist_flags); /* Decode File-Consistancy flags */ + H5F_decode_offset(new_file,p,new_file->smallobj_off); /* Decode offset of global small-object heap */ + H5F_decode_offset(new_file,p,new_file->freespace_off); /* Decode offset of global free-space heap */ + H5F_decode_length(new_file,p,new_file->logical_len); /* Decode logical length of file */ + + /* Decode the root symbol table entry */ + if (H5G_decode (new_file, &p, new_file->root_sym)<0) { + HGOTO_ERROR (H5E_IO, H5E_READERROR, FAIL); + } + + /* Get an atom for the file */ + if((ret_value=H5Aregister_atom(H5_FILE, new_file))==FAIL) + HGOTO_ERROR(H5E_ATOM, H5E_CANTREGISTER, FAIL); + +done: + if(ret_value == FAIL) + { /* Error condition cleanup */ + + /* Check if we left a dangling file handle */ + if(f_handle!=H5FI_INVALID_FILE) + H5FI_CLOSE(f_handle); /* close the file we opened */ + + /* Check if we left a dangling file struct */ + if(new_file) HDfree(new_file); + } + + /* Normal function cleanup */ + + FUNC_LEAVE(H5F_mask, ID_H5Fopen, ret_value); +} /* end H5Fopen() */ + +/*-------------------------------------------------------------------------- + NAME + H5Fclose + PURPOSE + Close an open HDF5 file. + USAGE + int32 H5Fclose(fid) + int32 fid; IN: File ID of file to close + RETURNS + SUCCEED/FAIL + DESCRIPTION + This function terminates access to an HDF5 file. If this is the last + file ID open for a file and if access IDs are still in use, this function + will fail. + + MODIFICATIONS: + Robb Matzke, 18 Jul 1997 + File struct destruction is through H5F_dest(). +--------------------------------------------------------------------------*/ +herr_t H5Fclose(hatom_t fid) +{ + CONSTR(FUNC, "H5Fclose"); /* for HERROR */ + hdf5_file_t *file=NULL; /* file struct for file to close */ + herr_t ret_value = SUCCEED; + + FUNC_ENTER(H5F_mask, ID_H5Fclose, H5F_init_interface, FAIL); + + /* Clear errors and check args and all the boring stuff. */ + H5ECLEAR; + if(H5Aatom_group(fid)!=H5_FILE) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL); + + /* Get the file handle to close */ + if((file=H5Aatom_object(fid))==NULL) + HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL); + + /* Decrement the ref. count and recycle the file structure */ + if((--file->ref_count)==0) + { + H5AC_flush (file, NULL, 0, TRUE); + if(file->file_handle!=H5FI_INVALID_FILE) { + H5FI_CLOSE(file->file_handle); + } + H5F_dest (file); + if(H5Aremove_atom(fid)==NULL) { + HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL); + } + } /* end if */ + +done: + if(ret_value == FAIL) + { /* Error condition cleanup */ + + } /* end if */ + + /* Normal function cleanup */ + FUNC_LEAVE(H5F_mask, ID_H5Fclose, ret_value); +} /* end H5Fclose() */ + + +/*------------------------------------------------------------------------- + * Function: H5F_block_read + * + * Purpose: Reads some data from a file/server/etc into a buffer. + * The data is contiguous. + * + * Return: Success: 0 + * + * Failure: -1 + * + * Programmer: Robb Matzke + * robb@maya.nuance.com + * Jul 10 1997 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +herr_t +H5F_block_read (hdf5_file_t *f, off_t addr, size_t size, void *buf) +{ + CONSTR(FUNC, "H5F_block_read"); /* for HERROR */ + + PABLO_TRACE_ON(H5F_mask, ID_H5F_block_read); + + if (0==size) return 0; + addr += f->file_create_parms.userblock_size; + + if (H5FI_SEEK (f->file_handle, addr)<0) + HRETURN_ERROR(H5E_IO, H5E_SEEKERROR, FAIL); + if (H5FI_READ (f->file_handle, buf, size)<0) + HRETURN_ERROR(H5E_IO, H5E_READERROR, FAIL); + PABLO_TRACE_OFF(H5F_mask, ID_H5F_block_read); + return SUCCEED; +} + + +/*------------------------------------------------------------------------- + * Function: H5F_block_write + * + * Purpose: Writes some data from memory to a file/server/etc. The + * data is contiguous. + * + * Return: Success: 0 + * + * Failure: -1 + * + * Programmer: Robb Matzke + * robb@maya.nuance.com + * Jul 10 1997 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +herr_t +H5F_block_write (hdf5_file_t *f, off_t addr, size_t size, void *buf) +{ + CONSTR(FUNC, "H5F_block_write"); /* for HERROR */ + + PABLO_TRACE_ON(H5F_mask, ID_H5F_block_read); + + if (0==size) return 0; + addr += f->file_create_parms.userblock_size; + + if (H5FI_SEEK (f->file_handle, addr)<0) + HRETURN_ERROR(H5E_IO, H5E_SEEKERROR, FAIL); + if (H5FI_WRITE (f->file_handle, buf, size)<0) + HRETURN_ERROR(H5E_IO, H5E_WRITEERROR, FAIL); + PABLO_TRACE_OFF(H5F_mask, ID_H5F_block_write); + return SUCCEED; +} diff --git a/src/H5Fprivate.h b/src/H5Fprivate.h new file mode 100644 index 0000000..2151b29 --- /dev/null +++ b/src/H5Fprivate.h @@ -0,0 +1,101 @@ +/**************************************************************************** + * NCSA HDF * + * Software Development Group * + * National Center for Supercomputing Applications * + * University of Illinois at Urbana-Champaign * + * 605 E. Springfield, Champaign IL 61820 * + * * + * For conditions of distribution and use, see the accompanying * + * hdf/COPYING file. * + * * + ****************************************************************************/ + +/* $Id$ */ + +/* + * This file contains macros & information for file access + */ + +#ifndef HDF5FILE_H +#define HDF5FILE_H + +#include "H5Fproto.h" /* Include Public Definitions */ + + /*****************************************/ + /*** This is the top level header file ***/ + /*** and shouldn't depend on any other ***/ + /*** packages! ***/ + /*****************************************/ + + + +#define SIZEOF_OFFSET(F) ((F)->file_create_parms.offset_size) +#define SIZEOF_SIZE(F) ((F)->file_create_parms.length_size) + +/* Size of the default error stack for file IDs */ +#define HDF5_FILE_ERRSTACK 16 + +/* Define the structure to store the file information for HDF5 files */ +typedef struct { + char *dir; /* Directory the file is located within */ + char *filename; /* Filename of file */ + uintn acc_perm; /* Access Permissions for file */ + hdf_file_t file_handle; /* File handle for actual I/O */ + int32 file_err; /* Error stack ID for this file */ + uintn ref_count; /* Reference count for number of times file is opened */ + uint32 consist_flags; /* File Consistency Flags */ + size_t smallobj_off; /* Offset of small-object heap within the file */ + size_t freespace_off; /* Offset of free-space info within the file */ + size_t logical_len; /* Logical length of file */ + struct H5AC_cache_t *cache; /* The object cache */ + file_create_temp_t file_create_parms; /* File-creation template parameters */ +#ifdef LATER + file_access_temp_t file_access_parms; /* File-access template parameters */ +#endif /* LATER */ + struct H5G_entry_t *root_sym; /* Extra for the root symbol in the file */ + } hdf5_file_t; + +/* Define a macro to ease calculation of the symbol-table entry size */ +#define H5F_symbol_table_size(f) (4+ /* "Symbol-type" bytes */ \ + f->file_create_parms.offset_size+ /* Offset bytes */ \ + f->file_create_parms.length_size+ /* Length bytes */ \ + 4+ /* Name offset in local heap */ \ + 24) /* "Scratch" space */ \ + +#ifdef NOT_YET +#define H5F_encode_offset(f,p,o) (f->file_create_parms.offset_size==4 ? UINT32ENCODE(p,o) \ + : f->file_create_parms.offset_size==8 ? UINT64ENCODE(p,o) \ + : f->file_create_parms.offset_size==2 ? UINT16ENCODE(p,o) \ + : H5FPencode_unusual_offset(f,&(p),(uint8 *)&(o))) +#else /* NOT_YET */ +#define H5F_encode_offset(f,p,o) switch(f->file_create_parms.offset_size) { case 4: UINT32ENCODE(p,o); break;\ + case 8: UINT64ENCODE(p,o); break;\ + case 2: UINT16ENCODE(p,o); break;} +#endif /* NOT_YET */ +#define H5F_decode_offset(f,p,o) switch(f->file_create_parms.offset_size) { case 4: UINT32DECODE(p,o); break;\ + case 8: UINT64DECODE(p,o); break;\ + case 2: UINT16DECODE(p,o); break;} + +#ifdef NOT_YET +#define H5F_encode_length(f,p,l) (f->file_create_parms.length_size==4 ? UINT32ENCODE(p,l) \ + : f->file_create_parms.length_size==8 ? UINT64ENCODE(p,l) \ + : f->file_create_parms.length_size==2 ? UINT16ENCODE(p,l) : H5FPencode_unusual_length(f,&(p),(uint8 *)&(l))) +#else /* NOT_YET */ +#define H5F_encode_length(f,p,l) switch(f->file_create_parms.length_size) { case 4: UINT32ENCODE(p,l); break;\ + case 8: UINT64ENCODE(p,l); break;\ + case 2: UINT16ENCODE(p,l); break;} +#endif /* NOT_YET */ + +#define H5F_decode_length(f,p,l) switch(f->file_create_parms.length_size) { case 4: UINT32DECODE(p,l); break;\ + case 8: UINT64DECODE(p,l); break;\ + case 2: UINT16DECODE(p,l); break;} + +/* Private functions, not part of the publicly documented API */ +void H5F_encode_length_unusual(const hdf5_file_t *f, uint8 **p, uint8 *l); +void H5F_encode_offset_unusual(const hdf5_file_t *f, uint8 **p, uint8 *o); +intn H5F_compare_filename(const VOIDP obj, const VOIDP key); +herr_t H5F_block_read (hdf5_file_t *f, off_t addr, size_t size, void *buf); +herr_t H5F_block_write (hdf5_file_t *f, off_t addr, size_t size, void *buf); + +#endif /* HDF5FILE_H */ + diff --git a/src/H5Fproto.h b/src/H5Fproto.h new file mode 100644 index 0000000..0600179 --- /dev/null +++ b/src/H5Fproto.h @@ -0,0 +1,43 @@ +/**************************************************************************** + * NCSA HDF * + * Software Development Group * + * National Center for Supercomputing Applications * + * University of Illinois at Urbana-Champaign * + * 605 E. Springfield, Champaign IL 61820 * + * * + * For conditions of distribution and use, see the accompanying * + * hdf/COPYING file. * + * * + ****************************************************************************/ + +/* $Id$ */ + +/* + * This file contains function prototypes for each exported function in the H5F module + */ + +#ifndef H5FPROTO_H +#define H5FPROTO_H + +/* file access codes */ +#define H5ACC_WRITE 0x0001 /* User in H5Fopen to open a file with write access */ +#define H5ACC_OVERWRITE 0x0002 /* User in H5Fcreate truncate an existing file */ + +#if defined c_plusplus || defined __cplusplus +extern "C" +{ +#endif /* c_plusplus || __cplusplus */ + +/* Functions in H5F.c */ +hbool_t H5Fis_hdf5(const char *filename); +hatom_t H5Fcreate(const char *filename, uintn flags, hatom_t create_template, hatom_t access_template); +hatom_t H5Fopen(const char *filename, uintn flags, hatom_t access_template); +herr_t H5Fclose(hatom_t fid); +hatom_t H5Fget_create_template(hatom_t fid); + +#if defined c_plusplus || defined __cplusplus +} +#endif /* c_plusplus || __cplusplus */ + +#endif /* H5FPROTO_H */ + diff --git a/src/H5G.c b/src/H5G.c new file mode 100644 index 0000000..fafecac --- /dev/null +++ b/src/H5G.c @@ -0,0 +1,196 @@ +/*------------------------------------------------------------------------- + * Copyright (C) 1997 National Center for Supercomputing Applications. + * All rights reserved. + * + *------------------------------------------------------------------------- + * + * Created: H5G.c + * Jul 18 1997 + * Robb Matzke <robb@maya.nuance.com> + * + * Purpose: + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +#include <assert.h> + +#include "hdf5.h" + +/* Packages needed by this file... */ +#include "H5Gprivate.h" + +/* PRIVATE PROTOTYPES */ + + +/*------------------------------------------------------------------------- + * Function: H5G_decode_vec + * + * Purpose: Same as H5G_decode() except it does it for an array of + * symbol table entries. + * + * Return: Success: 0, with *pp pointing to the first byte + * after the last symbol. + * + * Failure: -1 + * + * Programmer: Robb Matzke + * robb@maya.nuance.com + * Jul 18 1997 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +herr_t +H5G_decode_vec (hdf5_file_t *f, uint8 **pp, H5G_entry_t *ent, intn n) +{ + intn i; + + for (i=0; i<n; i++) { + if (H5G_decode (f, pp, ent+i)<0) return -1; + } + return 0; +} + + +/*------------------------------------------------------------------------- + * Function: H5G_decode + * + * Purpose: Decodes a symbol table entry pointed to by `*pp'. + * + * Return: Success: 0 with *pp pointing to the first byte + * following the symbol table entry. + * + * Failure: -1 + * + * Programmer: Robb Matzke + * robb@maya.nuance.com + * Jul 18 1997 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +herr_t +H5G_decode (hdf5_file_t *f, uint8 **pp, H5G_entry_t *ent) +{ + uint8 *p_ret = *pp; + + H5F_decode_offset (f, *pp, ent->name_off); + H5F_decode_offset (f, *pp, ent->header); + UINT32DECODE (*pp, ent->type); + + switch (ent->type) { + case H5G_NOTHING_CACHED: + break; + + case H5G_CACHED_SDATA: + UINT32DECODE (*pp, ent->cache.sdata.nt); + UINT32DECODE (*pp, ent->cache.sdata.ndim); + UINT32DECODE (*pp, ent->cache.sdata.dim[0]); + UINT32DECODE (*pp, ent->cache.sdata.dim[1]); + UINT32DECODE (*pp, ent->cache.sdata.dim[2]); + UINT32DECODE (*pp, ent->cache.sdata.dim[3]); + break; + + case H5G_CACHED_SYMTAB: + UINT32DECODE (*pp, ent->cache.symtab.btree); + UINT32DECODE (*pp, ent->cache.symtab.heap); + break; + + default: + abort(); + } + + *pp = p_ret + 2*SIZEOF_OFFSET(f) + 4 + 24; + return 0; +} + + +/*------------------------------------------------------------------------- + * Function: H5G_encode_vec + * + * Purpose: Same as H5G_encode() except it does it for an array of + * symbol table entries. + * + * Return: Success: 0, with *pp pointing to the first byte + * after the last symbol. + * + * Failure: -1 + * + * Programmer: Robb Matzke + * robb@maya.nuance.com + * Jul 18 1997 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +herr_t +H5G_encode_vec (hdf5_file_t *f, uint8 **pp, H5G_entry_t *ent, intn n) +{ + intn i; + + for (i=0; i<n; i++) { + if (H5G_encode (f, pp, ent+i)<0) return -1; + } + return 0; +} + + +/*------------------------------------------------------------------------- + * Function: H5G_encode + * + * Purpose: Encodes the specified symbol table entry into the buffer + * pointed to by *pp. + * + * Return: Success: 0, with *pp pointing to the first byte + * after the symbol table entry. + * + * Failure: -1 + * + * Programmer: Robb Matzke + * robb@maya.nuance.com + * Jul 18 1997 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +herr_t +H5G_encode (hdf5_file_t *f, uint8 **pp, H5G_entry_t *ent) +{ + uint8 *p_ret = *pp; + + H5F_encode_offset (f, *pp, ent->name_off); + H5F_encode_offset (f, *pp, ent->header); + UINT32ENCODE (*pp, ent->type); + + switch (ent->type) { + case H5G_NOTHING_CACHED: + break; + + case H5G_CACHED_SDATA: + UINT32ENCODE (*pp, ent->cache.sdata.nt); + UINT32ENCODE (*pp, ent->cache.sdata.ndim); + UINT32ENCODE (*pp, ent->cache.sdata.dim[0]); + UINT32ENCODE (*pp, ent->cache.sdata.dim[1]); + UINT32ENCODE (*pp, ent->cache.sdata.dim[2]); + UINT32ENCODE (*pp, ent->cache.sdata.dim[3]); + break; + + case H5G_CACHED_SYMTAB: + UINT32ENCODE (*pp, ent->cache.symtab.btree); + UINT32ENCODE (*pp, ent->cache.symtab.heap); + break; + + default: + abort(); + } + + *pp = p_ret + 2*SIZEOF_OFFSET(f) + 4 + 24; + return 0; +} + diff --git a/src/H5Gnode.c b/src/H5Gnode.c new file mode 100644 index 0000000..733e637 --- /dev/null +++ b/src/H5Gnode.c @@ -0,0 +1,661 @@ +/*------------------------------------------------------------------------- + * Copyright (C) 1997 National Center for Supercomputing Applications. + * All rights reserved. + * + *------------------------------------------------------------------------- + * + * Created: snode.c + * Jun 26 1997 + * Robb Matzke <matzke@llnl.gov> + * + * Purpose: Functions for handling symbol table nodes. A + * symbol table node is a small collection of symbol + * table entries. A B-tree usually points to the + * symbol table nodes for any given symbol table. + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +#include <assert.h> +#include <stdio.h> +#include <string.h> + +#include "hdf5.h" + +/* Packages needed by this file... */ +#include "H5ACprivate.h" /*cache */ +#include "H5Bprivate.h" /*B-link trees */ +#include "H5Gprivate.h" /*me */ +#include "H5Hprivate.h" /*heap */ +#include "H5MFprivate.h" /*file memory management */ +#include "H5MMprivate.h" /*core memory management */ + +/* PRIVATE PROTOTYPES */ +static void H5G_node_decode_key (hdf5_file_t *f, uint8 *raw, void *_key); +static void H5G_node_encode_key (hdf5_file_t *f, uint8 *raw, void *_key); +static size_t H5G_node_size (hdf5_file_t *f); +static off_t H5G_node_new (hdf5_file_t *f, void *_lt_key, void *_udata, + void *_rt_key); +static herr_t H5G_node_flush (hdf5_file_t *f, hbool_t destroy, off_t addr, + H5G_node_t *sym); +static H5G_node_t *H5G_node_load (hdf5_file_t *f, off_t addr, + const void *_data); +static intn H5G_node_cmp (hdf5_file_t *f, void *_lt_key, void *_udata, + void *_rt_key); +static herr_t H5G_node_found (hdf5_file_t *f, off_t addr, void *_lt_key, + void *_udata, void *_rt_key); +static off_t H5G_node_insert (hdf5_file_t *f, off_t addr, intn *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 (hdf5_file_t *f, off_t addr, void *_udata); +static size_t H5G_node_sizeof_rkey (hdf5_file_t *f); + +/* H5G inherits cache-like properties from H5AC */ +static const H5AC_class_t H5AC_SNODE[1] = {{ + (void*(*)(hdf5_file_t*,off_t,const void*))H5G_node_load, + (herr_t(*)(hdf5_file_t*,hbool_t,off_t,void*))H5G_node_flush, +}}; + +/* H5G inherits B-tree like properties from H5B */ +static const H5B_class_t H5B_SNODE[1] = {{ + 0, /*id */ + 64, /*k */ + sizeof (H5G_node_key_t), /*sizeof_nkey */ + H5G_node_sizeof_rkey, /*get_sizeof_rkey */ + H5G_node_new, /*new */ + H5G_node_cmp, /*cmp */ + H5G_node_found, /*found */ + H5G_node_insert, /*insert */ + H5G_node_list, /*list */ + H5G_node_decode_key, /*decode */ + H5G_node_encode_key, /*encode */ +}}; + + +/*------------------------------------------------------------------------- + * Function: H5G_node_sizeof_rkey + * + * Purpose: Returns the size of a raw B-link tree key for the specified + * file. + * + * Return: Success: Size of the key. + * + * Failure: never fails + * + * Programmer: Robb Matzke + * robb@maya.nuance.com + * Jul 14 1997 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static size_t +H5G_node_sizeof_rkey (hdf5_file_t *f) +{ + return SIZEOF_OFFSET(f); +} + + +/*------------------------------------------------------------------------- + * Function: H5G_node_decode_key + * + * Purpose: Decodes a raw key into a native key. + * + * Return: void + * + * Programmer: Robb Matzke + * robb@maya.nuance.com + * Jul 8 1997 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static void +H5G_node_decode_key (hdf5_file_t *f, uint8 *raw, void *_key) +{ + H5G_node_key_t *key = (H5G_node_key_t *)_key; + + H5F_decode_offset (f, raw, key->offset); +} + + +/*------------------------------------------------------------------------- + * Function: H5G_node_encode_key + * + * Purpose: Encodes a native key into a raw key. + * + * Return: void + * + * Programmer: Robb Matzke + * robb@maya.nuance.com + * Jul 8 1997 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static void +H5G_node_encode_key (hdf5_file_t *f, uint8 *raw, void *_key) +{ + H5G_node_key_t *key = (H5G_node_key_t *)_key; + + H5F_encode_offset (f, raw, key->offset); +} + + +/*------------------------------------------------------------------------- + * Function: H5G_node_size + * + * Purpose: Returns the total size of a symbol table node. + * + * Return: Success: Total size of the node in bytes. + * + * Failure: Never fails. + * + * Programmer: Robb Matzke + * robb@maya.nuance.com + * Jun 23 1997 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static size_t +H5G_node_size (hdf5_file_t *f) +{ + return H5G_HDR_SIZE(f) + (2*H5G_NODE_K) * (2*SIZEOF_OFFSET(f)); +} + + +/*------------------------------------------------------------------------- + * Function: H5G_node_new + * + * Purpose: Creates a new empty symbol table. This function is called + * by the B-tree insert function for an empty tree. It is + * also called internally to split a symbol node with + * LT_KEY and RT_KEY null pointers. + * + * Return: Success: Address of symbol table node. + * + * Failure: 0 + * + * Programmer: Robb Matzke + * robb@maya.nuance.com + * Jun 23 1997 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static off_t +H5G_node_new (hdf5_file_t *f, void *_lt_key, void *_udata, void *_rt_key) +{ + H5G_node_key_t *lt_key = (H5G_node_key_t*)_lt_key; + H5G_node_key_t *rt_key = (H5G_node_key_t*)_rt_key; + H5G_node_t *sym = H5MM_xcalloc (1, sizeof(H5G_node_t)); + size_t size = H5G_node_size (f); + off_t addr = H5MF_alloc (f, size); + + sym->dirty = 1; + sym->entry = H5MM_xcalloc (2 * H5G_NODE_K, sizeof(H5G_entry_t)); + H5AC_set (f, H5AC_SNODE, addr, sym); + + /* + * The left and right symbols in an empty tree are both the + * empty string stored at offset zero by the symtab.c functions. This + * allows the comparison functions to work correctly without knowing + * that there are no symbols. + */ + if (lt_key) lt_key->offset = 0; + if (rt_key) rt_key->offset = 0; + return addr; +} + + +/*------------------------------------------------------------------------- + * Function: H5G_node_flush + * + * Purpose: Flush a symbol table node to disk. + * + * Return: Success: 0 + * + * Failure: -1 + * + * Programmer: Robb Matzke + * robb@maya.nuance.com + * Jun 23 1997 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static herr_t +H5G_node_flush (hdf5_file_t *f, hbool_t destroy, off_t addr, H5G_node_t *sym) +{ + uint8 *buf=NULL, *p=NULL; + size_t size; + + if (sym->dirty) { + size = H5G_node_size (f); + buf = p = H5MM_xmalloc (size); + + /* magic number */ + HDmemcpy (p, H5G_NODE_MAGIC, 4); + p += 4; + + /* version number */ + *p++ = H5G_NODE_VERS; + + /* reserved */ + *p++ = 0; + + /* number of symbols */ + UINT16ENCODE (p, sym->nsyms); + + /* entries */ + H5G_encode_vec (f, &p, sym->entry, sym->nsyms); + + + H5F_block_write (f, addr, p-buf, buf); + buf = H5MM_xfree (buf); + } + + if (destroy) { + sym->entry = H5MM_xfree (sym->entry); + H5MM_xfree (sym); + } + + return 0; +} + + +/*------------------------------------------------------------------------- + * Function: H5G_node_load + * + * Purpose: Loads a symbol table from the file. + * + * Return: Success: Ptr to the new table. + * + * Failure: NULL + * + * Programmer: Robb Matzke + * robb@maya.nuance.com + * Jun 23 1997 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static H5G_node_t * +H5G_node_load (hdf5_file_t *f, off_t addr, const void *_udata) +{ + H5G_node_t *sym = H5MM_xcalloc (1, sizeof(H5G_node_t)); + size_t size = H5G_node_size (f); + uint8 *buf = H5MM_xmalloc (size); + uint8 *p = buf; + + + sym->entry = H5MM_xcalloc (2*H5G_NODE_K, sizeof(H5G_entry_t)); + H5F_block_read (f, addr, size, buf); + + /* magic */ + if (HDmemcmp (p, H5G_NODE_MAGIC, 4)) goto error; + p += 4; + + /* version */ + if (H5G_NODE_VERS!=*p++) goto error; + + /* reserved */ + p++; + + /* number of symbols */ + UINT16DECODE (p, sym->nsyms); + + /* entries */ + H5G_decode_vec (f, &p, sym->entry, sym->nsyms); + + H5MM_xfree (buf); + return sym; + +error: + H5MM_xfree (buf); + H5MM_xfree (sym); + return NULL; +} + + +/*------------------------------------------------------------------------- + * Function: H5G_node_cmp + * + * Purpose: Compares two keys from a B-tree node (LEFT and RIGHT) + * 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. + * + * positive if the UDATA key is greater + * than the RIGHT key. + * + * zero if the UDATA key falls between + * the LEFT key (exclusive) and the + * RIGHT key (inclusive). + * + * Failure: Never fails + * + * Programmer: Robb Matzke + * robb@maya.nuance.com + * Jun 23 1997 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static intn +H5G_node_cmp (hdf5_file_t *f, void *_lt_key, void *_udata, void *_rt_key) +{ + H5G_node_ud1_t *udata = (H5G_node_ud1_t *)_udata; + H5G_node_key_t *lt_key = (H5G_node_key_t *)_lt_key; + H5G_node_key_t *rt_key = (H5G_node_key_t *)_rt_key; + const char *s; + + /* left side */ + s = H5H_peek (f, udata->heap, lt_key->offset); + if (HDstrcmp (udata->name, s)<=0) return -1; + + /* right side */ + s = H5H_peek (f, udata->heap, rt_key->offset); + if (HDstrcmp (udata->name, s)>0) return 1; + + return 0; +} + + +/*------------------------------------------------------------------------- + * Function: H5G_node_found + * + * Purpose: The B-tree search engine has found the symbol table node + * which contains the requested symbol if the symbol exists. + * This function should examine that node for the symbol and + * return information about the symbol through the UDATA + * structure which contains the symbol name on function + * entry. + * + * Return: Success: 0 if found and data returned through the + * UDATA pointer. + * + * Failure: -1 if not found. + * + * Programmer: Robb Matzke + * robb@maya.nuance.com + * Jun 23 1997 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static herr_t +H5G_node_found (hdf5_file_t *f, off_t addr, void *_lt_key, void *_udata, + void *_rt_key) +{ + H5G_node_ud1_t *udata = (H5G_node_ud1_t *)_udata; + H5G_node_t *sn; + intn lt=0, idx=0, rt, cmp=1; + const char *s; + + sn = H5AC_find (f, H5AC_SNODE, addr, NULL); + if (!sn) return -1; + rt = sn->nsyms; + + /* + * Binary search. + */ + while (lt<rt && cmp) { + idx = (lt + rt) / 2; + sn = H5AC_find (f, H5AC_SNODE, addr, NULL); + s = H5H_peek (f, udata->heap, sn->entry[idx].name_off); + cmp = HDstrcmp (udata->name, s); + + if (cmp<0) { + rt = idx; + } else { + lt = idx+1; + } + } + if (cmp) return -1; + + udata->entry = sn->entry[idx]; + return 0; +} + + +/*------------------------------------------------------------------------- + * Function: H5G_node_insert + * + * Purpose: The B-tree insertion engine has found the symbol table node + * which should receive the new symbol/address pair. This + * function adds it to that node unless it already existed. + * + * If the node has no room for the symbol then the node is + * split into two nodes. The original node contains the + * low values and the new node contains the high values. + * The new symbol table entry is added to either node as + * appropriate. When a split occurs, this function will + * write the maximum key of the low node to the MID buffer + * and return the address of the new node. + * + * If the new key is larger than RIGHT then update RIGHT + * with the new key. + * + * Return: Success: Address of new node if the node was + * split. MID has been initialized with + * the high key of the left node, RIGHT + * has the high key of the right node. + * + * Zero if the node didn't split. RIGHT has the + * high key of the right node. + * + * Failure: -1 + * + * Programmer: Robb Matzke + * robb@maya.nuance.com + * Jun 24 1997 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static off_t +H5G_node_insert (hdf5_file_t *f, off_t addr, intn *anchor, + void *_lt_key, hbool_t *lt_key_changed, + void *_md_key, void *_udata, + void *_rt_key, hbool_t *rt_key_changed) +{ + H5G_node_key_t *md_key = (H5G_node_key_t *)_md_key; + H5G_node_key_t *rt_key = (H5G_node_key_t *)_rt_key; + H5G_node_ud1_t *udata = (H5G_node_ud1_t *)_udata; + + H5G_node_t *sn; + H5G_entry_t ent[2*H5G_NODE_K]; + off_t new_node=0, offset; + const char *s; + intn idx=-1, nsyms, cmp=1; + intn lt=0, rt; /*binary search cntrs */ + + /* + * 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 and buffer the entries so we don't have to + * worry about the cached value disappearing. + */ + sn = H5AC_find (f, H5AC_SNODE, addr, NULL); + if (!sn) return -1; + HDmemcpy (ent, sn->entry, sn->nsyms * sizeof(H5G_entry_t)); + rt = nsyms = sn->nsyms; + sn = NULL; + + /* + * Where does the new symbol get inserted? We use a binary search. + */ + while (lt<rt) { + idx = (lt + rt) / 2; + s = H5H_peek (f, udata->heap, ent[idx].name_off); + if (0==(cmp=HDstrcmp (udata->name, s))) return -1; /*already present*/ + if (cmp<0) { + rt = idx; + } else { + lt = idx+1; + } + } + idx += cmp>0 ? 1 : 0; + + /* + * Add the new name to the heap. The caller will check if the + * heap address changed and update the symbol table object header + * with the new heap address. + */ + offset = H5H_insert (f, udata->heap, strlen(udata->name)+1, udata->name); + + if (nsyms>=2*H5G_NODE_K) { + /* + * The node is full. Split it into a left and right + * node and return the address of the new right node (the + * left node is at the same address as the original node). + */ + + /* The left node */ + sn = H5AC_find (f, H5AC_SNODE, addr, NULL); + HDmemset (sn->entry+H5G_NODE_K, 0, H5G_NODE_K*sizeof(H5G_entry_t)); + sn->nsyms = H5G_NODE_K; + sn->dirty += 1; + + if (idx<=H5G_NODE_K) { + memmove (sn->entry+idx+1, sn->entry+idx, + (H5G_NODE_K-idx) * sizeof(H5G_entry_t)); + sn->entry[idx] = udata->entry; + sn->entry[idx].name_off = offset; + sn->nsyms += 1; + } + + /* The middle key */ + md_key->offset = sn->entry[sn->nsyms-1].name_off; + + /* The right node */ + new_node = H5G_node_new (f, NULL, NULL, NULL); + sn = H5AC_find (f, H5AC_SNODE, new_node, NULL); + HDmemcpy (sn->entry, ent+H5G_NODE_K, + H5G_NODE_K*sizeof(H5G_entry_t)); + sn->nsyms = H5G_NODE_K; + sn->dirty += 1; + + if (idx>H5G_NODE_K) { + idx -= H5G_NODE_K; + HDmemmove (sn->entry+idx+1, sn->entry+idx, + (H5G_NODE_K-idx) * sizeof (H5G_entry_t)); + sn->entry[idx] = udata->entry; + sn->entry[idx].name_off = offset; + sn->nsyms += 1; + + if (idx+1==sn->nsyms) { + rt_key->offset = offset; + *rt_key_changed = TRUE; + } + } + + } else { + /* + * Add the new symbol to the node. + */ + sn = H5AC_find (f, H5AC_SNODE, addr, NULL); + sn->dirty += 1; + HDmemmove (sn->entry+idx+1, sn->entry+idx, + (sn->nsyms-idx) * sizeof (H5G_entry_t)); + sn->nsyms += 1; + sn->entry[idx] = udata->entry; + sn->entry[idx].name_off = offset; + + if (idx+1==sn->nsyms) { + rt_key->offset = offset; + *rt_key_changed = TRUE; + } + } + + return new_node; +} + + +/*------------------------------------------------------------------------- + * Function: H5G_node_list + * + * Purpose: This function gets called during a directory list operation. + * It should fill in data in the UDATA struct. + * + * Return: Success: 0 + * + * Failure: -1 + * + * Programmer: Robb Matzke + * robb@maya.nuance.com + * Jun 24 1997 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static herr_t +H5G_node_list (hdf5_file_t *f, off_t addr, void *_udata) +{ + H5G_node_list_t *udata = (H5G_node_list_t *)_udata; + H5G_entry_t *ent; + intn i, nsyms; + const char *s; + H5G_node_t *sn; + + /* + * Read the symbol table and save the entry info. We save it + * in a separate buffer if names are requested because the name + * lookup may invalidate the symbol table. + */ + sn = H5AC_find (f, H5AC_SNODE, addr, NULL); + if (!sn) return -1; + nsyms = sn->nsyms; + if (udata->name) { + ent = H5MM_xmalloc (nsyms * sizeof(H5G_entry_t)); + HDmemcpy (ent, sn->entry, nsyms*sizeof(H5G_entry_t)); + sn = NULL; + } else { + ent = sn->entry; + } + + /* + * Gather the info. + */ + if (udata->name || udata->entry) { + for (i=0; i<nsyms && udata->nused<udata->nentries; i++) { + if (udata->name) { + s = H5H_peek (f, udata->heap, ent[i].name_off); + udata->name[udata->nused] = H5MM_xstrdup (s); + } + if (udata->entry) { + udata->entry[udata->nused] = ent[i]; + } + udata->nused += 1; + } + } else { + udata->nused += sn->nsyms; + } + + if (!sn) H5MM_xfree (ent); + return 0; +} + diff --git a/src/H5Gprivate.h b/src/H5Gprivate.h new file mode 100644 index 0000000..3316771 --- /dev/null +++ b/src/H5Gprivate.h @@ -0,0 +1,125 @@ +/*------------------------------------------------------------------------- + * Copyright (C) 1997 National Center for Supercomputing Applications. + * All rights reserved. + * + *------------------------------------------------------------------------- + * + * Created: H5Gprivate.h + * Jul 11 1997 + * Robb Matzke <robb@maya.nuance.com> + * + * Purpose: Private stuff for the H5G package (symbol tables). + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +#ifndef _H5Gprivate_H +#define _H5Gprivate_H + +#include "H5Gproto.h" /*include public declarations */ + +#include "H5Fprivate.h" /*include packages needed by this header*/ + +#define H5G_NODE_MAGIC "SNOD" /*symbol table node magic number */ +#define H5G_NODE_VERS 1 /*symbol table node version number */ +#define H5G_NODE_K 64 /*min degree. max degree is twice this */ +#define H5G_HDR_SIZE(F) 8 + +/* + * Various types of object header information can be cached in a symbol + * table entry (it's normal home is the object header to which the entry + * points). This datatype determines what (if anything) is cached in the + * symbol table entry. + */ +typedef enum H5G_type_t { + H5G_NOTHING_CACHED =0, /*nothing is cached */ + H5G_CACHED_SDATA =1, /*simple dataset, `sdata' */ + H5G_CACHED_SYMTAB =2 /*symbol table, `symtab' */ +} H5G_type_t; + +/* + * A symbol table entry. The two important fields are `name_off' and + * `header'. The remaining fields are used for caching information that + * also appears in the object header to which this symbol table entry + * points. + */ +typedef struct H5G_entry_t { + off_t name_off; /*offset of name within name heap */ + off_t header; /*file address of object header */ + H5G_type_t type; /*type of information cached */ + + union { + struct { + uint32 nt; /*number type */ + uint32 ndim; /*number of dimensions */ + uint32 dim[4]; /*dimension sizes */ + } sdata; + + struct { + off_t btree; /*file address of symbol table B-tree */ + off_t heap; /*file address of symtab name heap */ + } symtab; + } cache; /*cached data from object header */ +} 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. + */ +typedef struct H5G_node_t { + int dirty; /*has cache been modified? */ + int nsyms; /*number of symbols */ + H5G_entry_t *entry; /*symbol table entries */ +} H5G_node_t; + +/* + * Each key field of the B-link tree that points to symbol table + * nodes consists of this structure... + */ +typedef struct H5G_node_key_t { + off_t offset; /*offset into heap for name */ +} H5G_node_key_t; + +/* + * Data exchange structure for symbol table nodes. This structure is + * passed through the B-link tree layer to the methods for the objects + * to which the B-link tree points. + */ +typedef struct H5G_node_ud1_t { + + /* downward */ + char *name; /*points to temporary memory */ + off_t heap; /*symbol table heap address */ + + /* upward */ + H5G_entry_t entry; /*symbol table entry */ + +} H5G_node_ud1_t; + +typedef struct H5G_node_list_t { + + /* downward */ + H5G_entry_t *entry; /*array of entries, alloc'd by caller */ + char **name; /*array of string ptrs, allocd by caller*/ + intn nentries; /*size of the ADDR and NAME arrays */ + off_t heap; /*heap address */ + + /* upward */ + intn nused; /*num. symbols processed */ + +} H5G_node_list_t; + +/* + * Library prototypes... + */ +herr_t H5G_decode (hdf5_file_t *f, uint8 **pp, H5G_entry_t *ent); +herr_t H5G_decode_vec (hdf5_file_t *f, uint8 **pp, H5G_entry_t *ent, intn n); +herr_t H5G_encode (hdf5_file_t *f, uint8 **pp, H5G_entry_t *ent); +herr_t H5G_encode_vec (hdf5_file_t *f, uint8 **pp, H5G_entry_t *ent, intn n); + + +#endif + diff --git a/src/H5Gproto.h b/src/H5Gproto.h new file mode 100644 index 0000000..5c7a66d --- /dev/null +++ b/src/H5Gproto.h @@ -0,0 +1,29 @@ +/*------------------------------------------------------------------------- + * Copyright (C) 1997 National Center for Supercomputing Applications. + * All rights reserved. + * + *------------------------------------------------------------------------- + * + * Created: H5Gproto.h + * Jul 11 1997 + * Robb Matzke <robb@maya.nuance.com> + * + * Purpose: Prototypes for the H5G package (symbol tables). + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +#ifndef _H5Gproto_H +#define _H5Gproto_H + +#if defined c_plusplus || defined __cplusplus +extern "C" +{ +#endif + +#if defined c_plusplus || defined __cplusplus +} +#endif + +#endif diff --git a/src/H5H.c b/src/H5H.c new file mode 100644 index 0000000..39ec56b --- /dev/null +++ b/src/H5H.c @@ -0,0 +1,653 @@ +/*------------------------------------------------------------------------- + * Copyright (C) 1997 National Center for Supercomputing Applications. + * All rights reserved. + * + *------------------------------------------------------------------------- + * + * Created: H5H.c + * Jul 16 1997 + * Robb Matzke <robb@maya.nuance.com> + * + * Purpose: Heap functions. + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +#include <assert.h> +#include "hdf5.h" + +#include "H5ACprivate.h" /*cache */ +#include "H5Hprivate.h" /*self */ +#include "H5MFprivate.h" /*file memory management */ +#include "H5MMprivate.h" /*core memory management */ + +#define H5H_MAGIC "HEAP" /*heap magic number */ +#define H5H_FREE_NULL 1 /*end of free list on disk */ +#define H5H_HDR_SIZE(F) (4+SIZEOF_SIZE(F)+2*SIZEOF_OFFSET(F)) +#define H5H_SIZEOF_FREE(F) (SIZEOF_SIZE(F)+SIZEOF_OFFSET(F)) + +typedef struct H5H_free_t { + off_t offset; /*offset of free block */ + size_t size; /*size of free block */ + struct H5H_free_t *prev; /*previous entry in free list */ + struct H5H_free_t *next; /*next entry in free list */ +} H5H_free_t; + +typedef struct H5H_t { + intn dirty; + off_t addr; /*address of data */ + size_t disk_alloc; /*data bytes allocated on disk */ + size_t mem_alloc; /*data bytes allocated in mem */ + uint8 *chunk; /*the chunk, including header */ + H5H_free_t *freelist; /*the free list */ +} H5H_t; + +static H5H_t *H5H_load (hdf5_file_t *f, off_t addr, const void *udata); +static herr_t H5H_flush (hdf5_file_t *f, hbool_t dest, off_t addr, + H5H_t *heap); + +/* + * H5H inherits cache-like properties from H5AC + */ +static const H5AC_class_t H5AC_HEAP[1] = {{ + (void*(*)(hdf5_file_t*,off_t,const void*))H5H_load, + (herr_t(*)(hdf5_file_t*,hbool_t,off_t,void*))H5H_flush, +}}; + + +/*------------------------------------------------------------------------- + * Function: H5H_new + * + * Purpose: Creates a new heap data structure on disk and caches it + * in memory. SIZE_HINT is a hint for the initial size of the + * data area of the heap. If size hint is invalid then a + * reasonable (but probably not optimal) size will be chosen. + * If the heap ever has to grow, then REALLOC_HINT is the + * minimum amount by which the heap will grow. + * + * Return: Success: File address of new heap. + * + * Failure: -1 + * + * Programmer: Robb Matzke + * robb@maya.nuance.com + * Jul 16 1997 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +off_t +H5H_new (hdf5_file_t *f, size_t size_hint) +{ + H5H_t *heap = NULL; + size_t total_size; /*total heap size on disk */ + off_t addr; /*heap file address */ + + assert (f); + size_hint = MAX (0, size_hint); + if (size_hint && size_hint<H5H_SIZEOF_FREE(f)) { + size_hint = H5H_SIZEOF_FREE(f); + } + + /* allocate file version */ + total_size = H5H_HDR_SIZE(f) + size_hint; + if ((addr = H5MF_alloc (f, total_size))<0) return -1; + + /* allocate memory version */ + heap = H5MM_xcalloc (1, sizeof(H5H_t)); + heap->addr = addr + H5H_HDR_SIZE(f); + heap->disk_alloc = size_hint; + heap->mem_alloc = size_hint; + heap->chunk = H5MM_xmalloc (H5H_HDR_SIZE(f) + size_hint); + + /* free list */ + if (size_hint) { + heap->freelist = H5MM_xmalloc (sizeof(H5H_free_t)); + heap->freelist->offset = 0; + heap->freelist->size = size_hint; + heap->freelist->prev = heap->freelist->next = NULL; + } else { + heap->freelist = NULL; + } + + /* add to cache */ + heap->dirty = 1; + H5AC_set (f, H5AC_HEAP, addr, heap); + + return addr; +} + + +/*------------------------------------------------------------------------- + * Function: H5H_load + * + * Purpose: Loads a heap from disk. + * + * Return: Success: Ptr to heap memory data structure. + * + * Failure: NULL + * + * Programmer: Robb Matzke + * robb@maya.nuance.com + * Jul 17 1997 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static H5H_t * +H5H_load (hdf5_file_t *f, off_t addr, const void *udata) +{ + uint8 hdr[20], *p; + H5H_t *heap = H5MM_xcalloc (1, sizeof(H5H_t)); + H5H_free_t *fl=NULL, *tail=NULL; + off_t free_block; + + assert (addr>0); + assert (H5H_HDR_SIZE(f) <= sizeof hdr); + assert (!udata); + + if (H5F_block_read (f, addr, H5H_HDR_SIZE(f), hdr)<0) goto error; + p = hdr; + + /* magic number */ + if (HDmemcmp (hdr, H5H_MAGIC, 4)) goto error; + p += 4; + + /* heap data size */ + H5F_decode_length (f, p, heap->disk_alloc); + heap->mem_alloc = heap->disk_alloc; + + /* free list head */ + H5F_decode_offset (f, p, free_block); + assert (-1==free_block || (free_block>=0 && free_block<heap->disk_alloc)); + + /* data */ + H5F_decode_offset (f, p, heap->addr); + heap->chunk = H5MM_xmalloc (H5H_HDR_SIZE(f) + heap->mem_alloc); + if (heap->disk_alloc && + H5F_block_read (f, heap->addr, heap->disk_alloc, + heap->chunk + H5H_HDR_SIZE(f))<0) { + goto error; + } + + /* free list */ + while (H5H_FREE_NULL!=free_block) { + assert (free_block>=0 && free_block<heap->disk_alloc); + fl = H5MM_xmalloc (sizeof (H5H_free_t)); + fl->offset = free_block; + fl->prev = tail; + fl->next = NULL; + if (tail) tail->next = fl; + tail = fl; + if (!heap->freelist) heap->freelist = fl; + + p = heap->chunk + H5H_HDR_SIZE(f) + free_block; + H5F_decode_offset (f, p, free_block); + H5F_decode_length (f, p, fl->size); + + assert (fl->offset + fl->size <= heap->disk_alloc); + } + return heap; + +error: + if (heap) { + heap->chunk = H5MM_xfree (heap->chunk); + H5MM_xfree (heap); + } + return NULL; +} + + +/*------------------------------------------------------------------------- + * Function: H5H_flush + * + * Purpose: Flushes a heap from memory to disk if it's dirty. Optionally + * deletes the heap from memory. + * + * Return: Success: 0 + * + * Failure: -1 + * + * Programmer: Robb Matzke + * robb@maya.nuance.com + * Jul 17 1997 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static herr_t +H5H_flush (hdf5_file_t *f, hbool_t destroy, off_t addr, H5H_t *heap) +{ + uint8 *p = heap->chunk; + H5H_free_t *fl = heap->freelist; + + if (heap->dirty) { + + /* + * If the heap grew larger than disk storage then move the + * data segment of the heap to a larger contiguous block of + * disk storage. + */ + if (heap->mem_alloc > heap->disk_alloc) { + H5MF_free (f, heap->addr, heap->disk_alloc); + heap->addr = H5MF_alloc (f, heap->mem_alloc); + heap->disk_alloc = heap->mem_alloc; + } + + /* + * Write the header. + */ + HDmemcpy (p, H5H_MAGIC, 4); p += 4; + H5F_encode_length (f, p, heap->mem_alloc); + H5F_encode_offset (f, p, fl?fl->offset:-1); + H5F_encode_offset (f, p, heap->addr); + + /* + * Write the free list. + */ + while (fl) { + p = heap->chunk + H5H_HDR_SIZE(f) + fl->offset; + if (fl->next) { + H5F_encode_offset (f, p, fl->next->offset); + } else { + H5F_encode_offset (f, p, H5H_FREE_NULL); + } + H5F_encode_length (f, p, fl->size); + fl = fl->next; + } + + /* + * Copy buffer to disk. + */ + if (heap->addr == addr + H5H_HDR_SIZE(f)) { + if (H5F_block_write (f, addr, H5H_HDR_SIZE(f)+heap->disk_alloc, + heap->chunk)<0) { + return -1; + } + } else { + if (H5F_block_write (f, addr, H5H_HDR_SIZE(f), heap->chunk)<0) { + return -1; + } + if (H5F_block_write (f, heap->addr, heap->disk_alloc, + heap->chunk + H5H_HDR_SIZE(f))<0) { + return -1; + } + } + + heap->dirty = 0; + } + + /* + * Should we destroy the memory version? + */ + if (destroy) { + heap->chunk = H5MM_xfree (heap->chunk); + while (heap->freelist) { + fl = heap->freelist; + heap->freelist = fl->next; + H5MM_xfree (fl); + } + H5MM_xfree (heap); + } + + return 0; +} + + +/*------------------------------------------------------------------------- + * Function: H5H_read + * + * Purpose: Reads some object (or part of an object) from the heap + * whose address is ADDR in file F. OFFSET is the byte offset + * from the beginning of the heap at which to begin reading + * and SIZE is the number of bytes to read. + * + * If BUF is the null pointer then a buffer is allocated by + * this function. + * + * Attempting to read past the end of an object may cause this + * function to fail. + * + * Return: Success: BUF (or the allocated buffer) + * + * Failure: NULL + * + * Programmer: Robb Matzke + * robb@maya.nuance.com + * Jul 16 1997 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +void * +H5H_read (hdf5_file_t *f, off_t addr, off_t offset, size_t size, void *buf) +{ + H5H_t *heap = H5AC_find (f, H5AC_HEAP, addr, NULL); + + assert (offset>=0 && offset<heap->mem_alloc); + assert (offset+size<=heap->mem_alloc); + + if (!buf) buf = H5MM_xmalloc (size); + HDmemcpy (buf, heap->chunk+H5H_HDR_SIZE(f)+offset, size); + return buf; +} + + +/*------------------------------------------------------------------------- + * Function: H5H_peek + * + * Purpose: This function is a more efficient version of H5H_read. + * Instead of copying a heap object into a caller-supplied + * buffer, this function returns a pointer directly into the + * cache where the heap is being held. Thus, the return pointer + * is valid only until the next call to the cache. + * + * The address of the heap is ADDR in file F. OFFSET is the + * byte offset of the object from the beginning of the heap and + * may include an offset into the interior of the object. + * + * Return: Success: Ptr to the object. The pointer points to + * a chunk of memory large enough to hold the + * object from the specified offset (usually + * the beginning of the object) to the end + * of the object. Do not attempt to read past + * the end of the object. + * + * Failure: NULL + * + * Programmer: Robb Matzke + * robb@maya.nuance.com + * Jul 16 1997 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +const void * +H5H_peek (hdf5_file_t *f, off_t addr, off_t offset) +{ + H5H_t *heap = H5AC_find (f, H5AC_HEAP, addr, NULL); + + assert (offset>=0 && offset<heap->mem_alloc); + return heap->chunk+H5H_HDR_SIZE(f)+offset; +} + + +/*------------------------------------------------------------------------- + * Function: H5H_remove_free + * + * Purpose: Removes free list element FL from the specified heap. + * + * Return: void + * + * Programmer: Robb Matzke + * robb@maya.nuance.com + * Jul 17 1997 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static void +H5H_remove_free (H5H_t *heap, H5H_free_t *fl) +{ + if (fl->prev) fl->prev->next = fl->next; + if (fl->next) fl->next->prev = fl->prev; + + if (!fl->prev) heap->freelist = fl->next; +} + + +/*------------------------------------------------------------------------- + * Function: H5H_insert + * + * Purpose: Inserts a new item into the heap. + * + * Return: Success: Offset of new item within heap. + * + * Failure: -1 + * + * Programmer: Robb Matzke + * robb@maya.nuance.com + * Jul 17 1997 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +off_t +H5H_insert (hdf5_file_t *f, off_t addr, size_t size, const void *buf) +{ + H5H_t *heap = H5AC_find (f, H5AC_HEAP, addr, NULL); + H5H_free_t *fl=NULL, *max_fl=NULL; + off_t offset = -1; + size_t need_more; + + heap->dirty += 1; + + /* + * Look for a free slot large enough for this object and which would + * leave zero or at least H5G_SIZEOF_FREE bytes left over. + */ + for (fl=heap->freelist; fl; fl=fl->next) { + if (fl->size>size && fl->size-size>=H5H_SIZEOF_FREE(f)) { + offset = fl->offset; + fl->offset += size; + fl->size -= size; + break; + } else if (fl->size==size) { + offset = fl->offset; + H5H_remove_free (heap, fl); + break; + } else if (!max_fl || max_fl->offset < fl->offset) { + max_fl = fl; + } + } + + + /* + * If no free chunk was large enough, then allocate more space and + * add it to the free list. If the heap ends with a free chunk, we + * can extend that free chunk. Otherwise we'll have to make another + * free chunk. If the heap must expand, we double its size. + */ + if (offset<0) { + + need_more = MAX (2*heap->mem_alloc, H5H_SIZEOF_FREE(f)); + need_more = MAX (need_more, size); + + if (max_fl && max_fl->offset+max_fl->size==heap->mem_alloc) { + /* + * Increase the size of the maximum free block. + */ + offset = max_fl->offset; + max_fl->offset += size; + max_fl->size += need_more - size; + + if (max_fl->size < H5H_SIZEOF_FREE(f)) { + if (max_fl->size) { + fprintf (stderr, "H5H_insert: lost %d bytes at line %d\n", + max_fl->size, __LINE__); + } + H5H_remove_free (heap, max_fl); + } + + } else { + /* + * Create a new free list element large enough that we can + * take some space out of it right away. + */ + offset = heap->mem_alloc; + if (need_more-size >= H5H_SIZEOF_FREE(f)) { + fl = H5MM_xmalloc (sizeof(H5H_free_t)); + fl->offset = heap->mem_alloc + size; + fl->size = need_more - size; + fl->prev = NULL; + fl->next = heap->freelist; + if (heap->freelist) heap->freelist->prev = fl; + heap->freelist = fl; + } else if (need_more>size) { + fprintf (stderr, "H5H_insert: lost %d bytes at line %d\n", + need_more-size, __LINE__); + } + } + + fprintf (stderr, "H5H_insert: resize mem buf from %lu to %lu bytes\n", + (unsigned long)(heap->mem_alloc), + (unsigned long)(heap->mem_alloc + need_more)); + heap->mem_alloc += need_more; + heap->chunk = H5MM_xrealloc (heap->chunk, + H5H_HDR_SIZE(f)+heap->mem_alloc); + } + + /* + * Copy the data into the heap + */ + HDmemcpy (heap->chunk + H5H_HDR_SIZE(f) + offset, buf, size); + return offset; +} + + +/*------------------------------------------------------------------------- + * Function: H5H_write + * + * Purpose: Writes (overwrites) the object (or part of object) stored + * in BUF to the heap at file address ADDR in file F. The + * writing begins at byte offset OFFSET from the beginning of + * the heap and continues for SIZE bytes. + * + * Do not partially write an object to create it; the first + * write for an object must be for the entire object. + * + * Return: Success: 0 + * + * Failure: -1 + * + * Programmer: Robb Matzke + * robb@maya.nuance.com + * Jul 16 1997 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +herr_t +H5H_write (hdf5_file_t *f, off_t addr, off_t offset, size_t size, + const void *buf) +{ + H5H_t *heap = H5AC_find (f, H5AC_HEAP, addr, NULL); + + assert (offset>=0 && offset<heap->mem_alloc); + assert (offset+size<=heap->mem_alloc); + assert (buf); + + heap->dirty += 1; + HDmemcpy (heap->chunk+H5H_HDR_SIZE(f)+offset, buf, size); + return 0; +} + + +/*------------------------------------------------------------------------- + * Function: H5H_remove + * + * Purpose: Removes an object or part of an object from the heap at + * address ADDR of file F. The object (or part) to remove + * begins at byte OFFSET from the beginning of the heap and + * continues for SIZE bytes. + * + * Once part of an object is removed, one must not attempt + * to access that part. Removing the beginning of an object + * results in the object OFFSET increasing by the amount + * truncated. Removing the end of an object results in + * object truncation. Removing the middle of an object results + * in two separate objects, one at the original offset and + * one at the first offset past the removed portion. + * + * Return: Success: 0 + * + * Failure: -1 + * + * Programmer: Robb Matzke + * robb@maya.nuance.com + * Jul 16 1997 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +herr_t +H5H_remove (hdf5_file_t *f, off_t addr, off_t offset, size_t size) +{ + H5H_t *heap = H5AC_find (f, H5AC_HEAP, addr, NULL); + H5H_free_t *fl = heap->freelist, *fl2 = NULL; + + assert (offset>=0 && offset<heap->mem_alloc); + assert (offset+size<=heap->mem_alloc); + + heap->dirty += 1; + + /* + * Check if this chunk can be prepended or appended to an already + * free chunk. It might also fall between two chunks in such a way + * that all three chunks can be combined into one. + */ + while (fl) { + if (offset + size == fl->offset) { + fl->offset = offset; + fl->size += size; + fl2 = fl->next; + while (fl2) { + if (fl2->offset + fl2->size == fl->offset) { + fl->offset = fl2->offset; + fl->size += fl2->size; + H5H_remove_free (heap, fl2); + return 0; + } + } + return 0; + + } else if (fl->offset + fl->size == offset) { + fl->size += size; + fl2 = fl->next; + while (fl2) { + if (fl->offset + fl->size == fl2->offset) { + fl->size += fl2->size; + H5H_remove_free (heap, fl2); + return 0; + } + } + return 0; + } + + fl = fl->next; + } + + + /* + * The amount which is being removed must be large enough to + * hold the free list data. If not, the freed chunk is forever + * lost. + */ + if (size < H5H_SIZEOF_FREE(f)) { + fprintf (stderr, "H5H_remove: lost %d bytes\n", size); + return 0; + } + + /* + * Add an entry to the free list. + */ + fl = H5MM_xmalloc (sizeof(H5H_free_t)); + fl->offset = offset; + fl->size = size; + fl->prev = NULL; + fl->next = heap->freelist; + if (heap->freelist) heap->freelist->prev = fl; + heap->freelist = fl; + + return 0; +} diff --git a/src/H5Hprivate.h b/src/H5Hprivate.h new file mode 100644 index 0000000..b90d727 --- /dev/null +++ b/src/H5Hprivate.h @@ -0,0 +1,36 @@ +/*------------------------------------------------------------------------- + * Copyright (C) 1997 National Center for Supercomputing Applications. + * All rights reserved. + * + *------------------------------------------------------------------------- + * + * Created: H5Hprivate.h + * Jul 16 1997 + * Robb Matzke <robb@maya.nuance.com> + * + * Purpose: + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +#ifndef _H5Hprivate_H +#define _H5Hprivate_H + +#include "H5Hproto.h" +#include "H5Fprivate.h" + +/* + * Library prototypes... + */ +off_t H5H_new (hdf5_file_t *f, size_t size_hint); +void *H5H_read (hdf5_file_t *f, off_t addr, off_t offset, size_t size, + void *buf); +const void *H5H_peek (hdf5_file_t *f, off_t addr, off_t offset); +off_t H5H_insert (hdf5_file_t *f, off_t addr, size_t size, const void *buf); +herr_t H5H_write (hdf5_file_t *f, off_t addr, off_t offset, size_t size, + const void *buf); +herr_t H5H_remove (hdf5_file_t *f, off_t addr, off_t offset, size_t size); + + +#endif diff --git a/src/H5Hproto.h b/src/H5Hproto.h new file mode 100644 index 0000000..fcf36f8 --- /dev/null +++ b/src/H5Hproto.h @@ -0,0 +1,29 @@ +/*------------------------------------------------------------------------- + * Copyright (C) 1997 National Center for Supercomputing Applications. + * All rights reserved. + * + *------------------------------------------------------------------------- + * + * Created: H5Hproto.h + * Jul 16 1997 + * Robb Matzke <robb@maya.nuance.com> + * + * Purpose: + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +#ifndef _H5Hproto_H +#define _H5Hproto_H + +#if defined c_plusplus || defined __cplusplus +extern "C" +{ +#endif + +#if defined c_plusplus || defined __cplusplus +} +#endif + +#endif diff --git a/src/H5M.c b/src/H5M.c new file mode 100644 index 0000000..6e8dc3a --- /dev/null +++ b/src/H5M.c @@ -0,0 +1,257 @@ +/**************************************************************************** +* NCSA HDF * +* Software Development Group * +* National Center for Supercomputing Applications * +* University of Illinois at Urbana-Champaign * +* 605 E. Springfield, Champaign IL 61820 * +* * +* For conditions of distribution and use, see the accompanying * +* hdf/COPYING file. * +* * +****************************************************************************/ + +#ifdef RCSID +static char RcsId[] = "@(#)$Revision$"; +#endif + +/* $Id$ */ + +/*LINTLIBRARY */ +/*+ + FILE + hdf5meta.c + HDF5 "Meta-Object" routines + + EXPORTED ROUTINES + H5Mcreate -- Create an object + H5Mcopy -- Copy an object + H5Mrelease -- Release access to an object + + LIBRARY-SCOPED ROUTINES + + LOCAL ROUTINES + H5M_init_interface -- initialize the interface + + */ + +#include "hdf5.h" +#include "H5private.h" /* Generic functions */ +#include "H5Cproto.h" /* Template interface */ +#include "H5Tproto.h" /* Datatype interface */ +#include "H5Mprivate.h" /* Meta-object interface */ +#include "H5Cprivate.h" /* Template interface */ + +/*--------------------- Locally scoped variables -----------------------------*/ + +/* Whether we've installed the library termination function yet for this interface */ +static intn interface_initialize = FALSE; + +/*------------------_-- Local function prototypes ----------------------------*/ +static herr_t H5M_init_interface(void); + +/*-------------------------------------------------------------------------- +NAME + H5M_init_interface -- Initialize interface-specific information +USAGE + herr_t H5M_init_interface() + +RETURNS + SUCCEED/FAIL +DESCRIPTION + Initializes any interface-specific data or routines. + +--------------------------------------------------------------------------*/ +static herr_t H5M_init_interface(void) +{ +#ifdef LATER + CONSTR(FUNC, "H5CIinit_interface"); /* For HERROR */ +#endif /* LATER */ + herr_t ret_value = SUCCEED; + + /* Don't use "FUNC_ENTER" macro, to avoid potential infinite recursion */ + PABLO_TRACE_ON(H5M_mask, ID_H5M_init_interface); + + /* Don't call this routine again... */ + interface_initialize = TRUE; + + FUNC_LEAVE(H5M_mask, ID_H5M_init_interface, ret_value); +} /* H5M_init_interface */ + +/*-------------------------------------------------------------------------- + NAME + H5M_find_type + PURPOSE + Find the type of meta-object to issue a method call on + USAGE + intn H5M_find_type(type) + hobjtype_t type; IN: Type of object to create + RETURNS + Returns the index of the type in the array of methods on success, or FAIL + on failure. + DESCRIPTION + This function performs a search to find the index of the type of a + meta-object in the array of function pointers. +--------------------------------------------------------------------------*/ +static intn H5M_find_type(hobjtype_t type) +{ + CONSTR(FUNC, "H5M_find_type"); /* for HERROR */ + intn i; /* local counting variable */ + intn ret_value = FAIL; + + FUNC_ENTER(H5M_mask, ID_H5M_find_type, H5M_init_interface, FAIL); + + /* Clear errors and check args and all the boring stuff. */ + H5ECLEAR; + + /* + * Currently this uses a stright linear search, which can easily be changed + * to a binary search when it becomes too slow. + */ + for(i=0; i<(sizeof(meta_func_arr)/sizeof(meta_func_t)); i++) + if(type==meta_func_arr[i].type) + HGOTO_DONE(i); + +done: + if(ret_value == FAIL) + { /* Error condition cleanup */ + + } /* end if */ + + /* Normal function cleanup */ + + FUNC_LEAVE(H5M_mask, ID_H5M_find_type, ret_value); +} /* end H5M_find_type() */ + +/*-------------------------------------------------------------------------- + NAME + H5Mcreate + PURPOSE + Create a new HDF5 object. + USAGE + hatom_t H5Mcreate(owner_id, type, name) + hatom_t owner_id; IN: Group/file which owns this object + hobjtype_t type; IN: Type of object to create + const char *name; IN: Name of the object + RETURNS + Returns ID (atom) on success, FAIL on failure + DESCRIPTION + This function re-directs the object's creation into the appropriate + interface, as defined by the function pointers in hdf5fptr.h +--------------------------------------------------------------------------*/ +hatom_t H5Mcreate(hatom_t owner_id, hobjtype_t type, const char *name) +{ + CONSTR(FUNC, "H5Mcreate"); /* for HERROR */ + intn i; /* local counting variable */ + hatom_t ret_value = SUCCEED; + + FUNC_ENTER(H5M_mask, ID_H5Mcreate, H5M_init_interface, FAIL); + + /* Clear errors and check args and all the boring stuff. */ + H5ECLEAR; + if(type<=BADGROUP || type>=MAXGROUP) + HGOTO_ERROR(H5E_ARGS, H5E_BADRANGE, FAIL); + + i=H5M_find_type(type); + if(meta_func_arr[i].create==NULL) + HGOTO_ERROR(H5E_INTERNAL, H5E_UNSUPPORTED, FAIL); + ret_value=meta_func_arr[i].create(owner_id,type,name); + +done: + if(ret_value == FAIL) + { /* Error condition cleanup */ + + } /* end if */ + + /* Normal function cleanup */ + + FUNC_LEAVE(H5M_mask, ID_H5Mcreate, ret_value); +} /* end H5Mcreate() */ + + +/*-------------------------------------------------------------------------- + NAME + H5Mcopy + PURPOSE + Copy an HDF5 object. + USAGE + hatom_t H5Mcopy(oid) + hatom_t oid; IN: Object to copy + RETURNS + SUCCEED/FAIL + DESCRIPTION + This function re-directs the object's copy into the appropriate + interface, as defined by the function pointers in hdf5fptr.h +--------------------------------------------------------------------------*/ +hatom_t H5Mcopy(hatom_t oid) +{ + CONSTR(FUNC, "H5Mcopy"); /* for HERROR */ + group_t group=H5Aatom_group(oid); /* Atom group for incoming object */ + intn i; /* local counting variable */ + herr_t ret_value = SUCCEED; + + FUNC_ENTER(H5M_mask, ID_H5Mcopy, H5M_init_interface, FAIL); + + /* Clear errors and check args and all the boring stuff. */ + H5ECLEAR; + if(group<=BADGROUP || group>=MAXGROUP) + HGOTO_ERROR(H5E_ARGS, H5E_BADRANGE, FAIL); + + i=H5M_find_type(group); + if(meta_func_arr[i].copy==NULL) + HGOTO_ERROR(H5E_INTERNAL, H5E_UNSUPPORTED, FAIL); + ret_value=meta_func_arr[i].copy(oid); + +done: + if(ret_value == FAIL) + { /* Error condition cleanup */ + + } /* end if */ + + /* Normal function cleanup */ + + FUNC_LEAVE(H5M_mask, ID_H5Mcopy, ret_value); +} /* end H5Mcopy() */ + +/*-------------------------------------------------------------------------- + NAME + H5Mrelease + PURPOSE + Release access to an HDF5 object. + USAGE + herr_t H5Mrelease(oid) + hatom_t oid; IN: Object to release access to + RETURNS + SUCCEED/FAIL + DESCRIPTION + This function re-directs the object's release into the appropriate + interface, as defined by the function pointers in hdf5fptr.h +--------------------------------------------------------------------------*/ +herr_t H5Mrelease(hatom_t oid) +{ + CONSTR(FUNC, "H5Mrelease"); /* for HERROR */ + group_t group=H5Aatom_group(oid); /* Atom group for incoming object */ + intn i; /* local counting variable */ + herr_t ret_value = SUCCEED; + + FUNC_ENTER(H5M_mask, ID_H5Mrelease, H5M_init_interface, FAIL); + + /* Clear errors and check args and all the boring stuff. */ + H5ECLEAR; + if(group<=BADGROUP || group>=MAXGROUP) + HGOTO_ERROR(H5E_ARGS, H5E_BADRANGE, FAIL); + + i=H5M_find_type(group); + if(meta_func_arr[i].release==NULL) + HGOTO_ERROR(H5E_INTERNAL, H5E_UNSUPPORTED, FAIL); + ret_value=meta_func_arr[i].release(oid); + +done: + if(ret_value == FAIL) + { /* Error condition cleanup */ + + } /* end if */ + + /* Normal function cleanup */ + + FUNC_LEAVE(H5M_mask, ID_H5Mrelease, ret_value); +} /* end H5Mrelease() */ + diff --git a/src/H5MF.c b/src/H5MF.c new file mode 100644 index 0000000..0bd1f4f --- /dev/null +++ b/src/H5MF.c @@ -0,0 +1,88 @@ +/*------------------------------------------------------------------------- + * Copyright (C) 1997 National Center for Supercomputing Applications. + * All rights reserved. + * + *------------------------------------------------------------------------- + * + * Created: H5MF.c + * Jul 11 1997 + * Robb Matzke <robb@maya.nuance.com> + * + * Purpose: File memory management functions. + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +#include <assert.h> +#include "hdf5.h" + +#include "H5Fprivate.h" +#include "H5MFprivate.h" + + +/*------------------------------------------------------------------------- + * Function: H5MF_alloc + * + * Purpose: Allocate at least SIZE bytes of file memory and return + * the address where that contiguous chunk of file memory + * exists. + * + * Return: Success: File address of new chunk. + * + * Failure: -1 + * + * Programmer: Robb Matzke + * robb@maya.nuance.com + * Jul 11 1997 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +off_t +H5MF_alloc (hdf5_file_t *f, size_t size) +{ + off_t addr; + + assert (f); + assert (f->logical_len>0); + assert (size>0); + + addr = f->logical_len; + f->logical_len += size; + return addr; +} + + +/*------------------------------------------------------------------------- + * Function: H5MF_free + * + * Purpose: Frees part of a file, making that part of the file + * available for reuse. + * + * Note: This version of the function doesn't do anything. + * + * Return: Success: 0 + * + * Failure: -1 + * + * Programmer: Robb Matzke + * robb@maya.nuance.com + * Jul 17 1997 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +herr_t +H5MF_free (hdf5_file_t *f, off_t addr, size_t size) +{ + if (addr<=0 || 0==size) return 0; + + fprintf (stderr, "H5MF_free: lost %lu bytes of file storage\n", + (unsigned long)size); + + return 0; +} + diff --git a/src/H5MFprivate.h b/src/H5MFprivate.h new file mode 100644 index 0000000..a040eda --- /dev/null +++ b/src/H5MFprivate.h @@ -0,0 +1,28 @@ +/*------------------------------------------------------------------------- + * Copyright (C) 1997 National Center for Supercomputing Applications. + * All rights reserved. + * + *------------------------------------------------------------------------- + * + * Created: H5MFprivate.h + * Jul 11 1997 + * Robb Matzke <robb@maya.nuance.com> + * + * Purpose: Private header file for file memory management. + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +#ifndef _H5MFprivate_H +#define _H5MFprivate_H + +#include "H5MFproto.h" + +/* + * Library prototypes... + */ +off_t H5MF_alloc (hdf5_file_t *f, size_t size); +herr_t H5MF_free (hdf5_file_t *f, off_t addr, size_t size); + +#endif diff --git a/src/H5MFproto.h b/src/H5MFproto.h new file mode 100644 index 0000000..3b54ecd --- /dev/null +++ b/src/H5MFproto.h @@ -0,0 +1,29 @@ +/*------------------------------------------------------------------------- + * Copyright (C) 1997 National Center for Supercomputing Applications. + * All rights reserved. + * + *------------------------------------------------------------------------- + * + * Created: H5MFproto.h + * Jul 11 1997 + * Robb Matzke <robb@maya.nuance.com> + * + * Purpose: Prototypes for file memory management. + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +#ifndef _H5MFproto_H +#define _H5MFproto_H + +#if defined c_plusplus || defined __cplusplus +extern "C" +{ +#endif + +#if defined c_plusplus || defined __cplusplus +} +#endif + +#endif diff --git a/src/H5MM.c b/src/H5MM.c new file mode 100644 index 0000000..725085f --- /dev/null +++ b/src/H5MM.c @@ -0,0 +1,175 @@ +/*------------------------------------------------------------------------- + * Copyright (C) 1997 National Center for Supercomputing Applications. + * All rights reserved. + * + *------------------------------------------------------------------------- + * + * Created: H5MM.c + * Jul 10 1997 + * Robb Matzke <robb@maya.nuance.com> + * + * Purpose: Memory management functions. + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +#include <assert.h> +#include "hdf5.h" + +#include "H5MMprivate.h" + + +/*------------------------------------------------------------------------- + * Function: H5MM_xmalloc + * + * Purpose: Just like malloc(3) except it aborts on an error. + * + * Return: Success: Ptr to new memory. + * + * Failure: abort() + * + * Programmer: Robb Matzke + * robb@maya.nuance.com + * Jul 10 1997 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +void * +H5MM_xmalloc (size_t size) +{ + void *mem = HDmalloc (size); + assert (mem); + return mem; +} + + +/*------------------------------------------------------------------------- + * Function: H5MM_xcalloc + * + * Purpose: Just like calloc(3) except it aborts on an error. + * + * Return: Success: Ptr to memory. + * + * Failure: abort() + * + * Programmer: Robb Matzke + * robb@maya.nuance.com + * Jul 10 1997 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +void * +H5MM_xcalloc (size_t n, size_t size) +{ + void *mem = HDcalloc (n, size); + assert (mem); + return mem; +} + + +/*------------------------------------------------------------------------- + * Function: H5MM_xrealloc + * + * Purpose: Just like the POSIX version of realloc(3) exept it aborts + * on an error. Specifically, the following calls are + * equivalent + * + * H5MM_xrealloc (NULL, size) <==> H5MM_xmalloc (size) + * H5MM_xrealloc (ptr, 0) <==> H5MM_xfree (ptr) + * H5MM_xrealloc (NULL, 0) <==> NULL + * + * Return: Success: Ptr to new memory or NULL if the memory + * was freed. + * + * Failure: abort() + * + * Programmer: Robb Matzke + * robb@maya.nuance.com + * Jul 10 1997 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +void * +H5MM_xrealloc (void *mem, size_t size) +{ + if (!mem) { + if (0==size) return NULL; + mem = H5MM_xmalloc (size); + + } else if (0==size) { + mem = H5MM_xfree (mem); + + } else { + mem = realloc (mem, size); + assert (mem); + } + + return mem; +} + + +/*------------------------------------------------------------------------- + * Function: H5MM_strdup + * + * Purpose: Duplicates a string. If the string to be duplicated is the + * null pointer, then return null. If the string to be duplicated + * is the empty string then return a new empty string. + * + * Return: Success: Ptr to a new string (or null if no string). + * + * Failure: abort() + * + * Programmer: Robb Matzke + * robb@maya.nuance.com + * Jul 10 1997 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +char * +H5MM_xstrdup (const char *s) +{ + char *mem; + + if (!s) return NULL; + mem = H5MM_xmalloc (strlen (s)+1); + strcpy (mem, s); + return mem; +} + + +/*------------------------------------------------------------------------- + * Function: H5MM_xfree + * + * Purpose: Just like free(3) except null pointers are allowed as + * arguments, and the return value (always NULL) can be + * assigned to the pointer whose memory was just freed: + * + * thing = H5MM_xfree (thing); + * + * Return: Success: NULL + * + * Failure: never fails + * + * Programmer: Robb Matzke + * robb@maya.nuance.com + * Jul 10 1997 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +void * +H5MM_xfree (void *mem) +{ + if (mem) HDfree (mem); + return NULL; +} diff --git a/src/H5MMprivate.h b/src/H5MMprivate.h new file mode 100644 index 0000000..68dd73b --- /dev/null +++ b/src/H5MMprivate.h @@ -0,0 +1,32 @@ +/*------------------------------------------------------------------------- + * Copyright (C) 1997 National Center for Supercomputing Applications. + * All rights reserved. + * + *------------------------------------------------------------------------- + * + * Created: H5MMprivate.h + * Jul 10 1997 + * Robb Matzke <robb@maya.nuance.com> + * + * Purpose: Private header for memory management. + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +#ifndef _H5MMprivate_H +#define _H5MMprivate_h + +#include "H5MMproto.h" + +/* + * Library prototypes... + */ +void *H5MM_xmalloc (size_t size); +void *H5MM_xcalloc (size_t n, size_t size); +void *H5MM_xrealloc (void *mem, size_t size); +char *H5MM_xstrdup (const char *s); +void *H5MM_xfree (void *mem); + + +#endif diff --git a/src/H5MMproto.h b/src/H5MMproto.h new file mode 100644 index 0000000..e1598f8 --- /dev/null +++ b/src/H5MMproto.h @@ -0,0 +1,29 @@ +/*------------------------------------------------------------------------- + * Copyright (C) 1997 National Center for Supercomputing Applications. + * All rights reserved. + * + *------------------------------------------------------------------------- + * + * Created: H5MMproto.h + * Jul 10 1997 + * Robb Matzke <robb@maya.nuance.com> + * + * Purpose: Function prototypes for memory management. + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +#ifndef _H5MMproto_H +#define _H5MMproto_H + +#if defined c_plusplus || defined __cplusplus +extern "C" +{ +#endif + +#if defined c_plusplus || defined __cplusplus +} +#endif + +#endif diff --git a/src/H5Mprivate.h b/src/H5Mprivate.h new file mode 100644 index 0000000..a1fb6cc --- /dev/null +++ b/src/H5Mprivate.h @@ -0,0 +1,86 @@ +/**************************************************************************** + * NCSA HDF * + * Software Development Group * + * National Center for Supercomputing Applications * + * University of Illinois at Urbana-Champaign * + * 605 E. Springfield, Champaign IL 61820 * + * * + * For conditions of distribution and use, see the accompanying * + * hdf/COPYING file. * + * * + ****************************************************************************/ + +/* $Id$ */ + +/* + * This file contains macros & information for meta-objects + */ + +#ifndef H5MPRIVATE_H +#define H5MPRIVATE_H + +#include "H5Mproto.h" /* Include Public Definitions */ + +/* + * A function table record for accessing interfaces which use the "meta" + * interface to create/access/release objects. + */ + +typedef struct meta_func_t + { + hobjtype_t type; /* Object type this interface is for */ + hatom_t (*create) (hatom_t , hobjtype_t, const char *); /* Object creation function */ + hatom_t (*access) (hatom_t ); /* Object access function */ + hatom_t (*copy) (hatom_t ); /* Object copy function */ + hatom_t (*find_name) (hatom_t , hobjtype_t, const char *); /* Find first object */ + uint32 (*name_len) (hatom_t ); /* Get length of object name */ + herr_t (*get_name) (hatom_t , char *); /* Get object name */ + herr_t (*set_name) (hatom_t , const char *); /* Set object name */ + hatom_t (*search) (hatom_t , hobjtype_t, const char *); /* Search for list of objects */ + hatom_t (*index) (hatom_t , hobjtype_t, uint32); /* Get the OID for the n'th object */ + herr_t (*flush) (hatom_t ); /* Flush the object to disk */ + herr_t (*delete) (hatom_t ); /* Delete an object from file */ + hatom_t (*get_parent) (hatom_t ); /* Get the parent object of an object */ + herr_t (*release) (hatom_t ); /* End access to an object */ + } +meta_func_t; + +meta_func_t meta_func_arr[]={ + { /* Template object meta-functions (defined in H5C.c) */ + H5_TEMPLATE, /* File-Creation Template Type ID */ + H5C_create, /* File-Creation Template Create */ + NULL, + H5C_copy, /* File-Creation Template Copy */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + H5C_release /* File-Creation Template Release */ + }, + { /* Datatype object meta-functions (defined in H5T.c) */ + H5_DATATYPE, /* Datatype Type ID */ + H5T_create, /* Datatype object functions */ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + H5T_release + } + }; + +/* Private functions, not part of the publicly documented API */ + +#endif /* H5MPRIVATE_H */ + diff --git a/src/H5Mproto.h b/src/H5Mproto.h new file mode 100644 index 0000000..3c06412 --- /dev/null +++ b/src/H5Mproto.h @@ -0,0 +1,37 @@ +/**************************************************************************** + * NCSA HDF * + * Software Development Group * + * National Center for Supercomputing Applications * + * University of Illinois at Urbana-Champaign * + * 605 E. Springfield, Champaign IL 61820 * + * * + * For conditions of distribution and use, see the accompanying * + * hdf/COPYING file. * + * * + ****************************************************************************/ + +/* $Id$ */ + +/* + * This file contains function prototypes for each exported function in the H5M module + */ + +#ifndef H5MPROTO_H +#define H5MPROTO_H + +#if defined c_plusplus || defined __cplusplus +extern "C" +{ +#endif /* c_plusplus || __cplusplus */ + +/* Functions in H5M.c */ +hatom_t H5Mcreate(hatom_t owner_id, hobjtype_t type, const char *name); +hatom_t H5Mcopy(hatom_t oid); +herr_t H5Mrelease(hatom_t oid); + +#if defined c_plusplus || defined __cplusplus +} +#endif /* c_plusplus || __cplusplus */ + +#endif /* H5MPROTO_H */ + diff --git a/src/H5P.c b/src/H5P.c new file mode 100644 index 0000000..ad24b07 --- /dev/null +++ b/src/H5P.c @@ -0,0 +1,216 @@ +/**************************************************************************** +* NCSA HDF * +* Software Development Group * +* National Center for Supercomputing Applications * +* University of Illinois at Urbana-Champaign * +* 605 E. Springfield, Champaign IL 61820 * +* * +* For conditions of distribution and use, see the accompanying * +* hdf/COPYING file. * +* * +****************************************************************************/ + +#ifdef RCSID +static char RcsId[] = "@(#)$Revision$"; +#endif + +/* $Id$ */ + +/*LINTLIBRARY */ +/*+ + FILE + H5P.c + HDF5 Data-space routines + + EXPORTED ROUTINES + H5Pcreate -- Create a data-space + H5Prelease -- Release access to a data-space + + LIBRARY-SCOPED ROUTINES + + LOCAL ROUTINES + H5P_init_interface -- initialize the interface + + */ + +#include "hdf5.h" +#include "H5private.h" /* Generic Functions */ +#include "H5Pprivate.h" /* Data-space functions */ + +/*--------------------- Locally scoped variables -----------------------------*/ + +/* Whether we've installed the library termination function yet for this interface */ +static intn interface_initialize = FALSE; + +/*-------------------------------------------------------------------------- +NAME + H5P_init_interface -- Initialize interface-specific information +USAGE + herr_t H5P_init_interface() + +RETURNS + SUCCEED/FAIL +DESCRIPTION + Initializes any interface-specific data or routines. + +--------------------------------------------------------------------------*/ +static herr_t H5P_init_interface(void) +{ +#ifdef LATER + CONSTR(FUNC, "H5P_init_interface"); /* For HERROR */ +#endif /* LATER */ + herr_t ret_value = SUCCEED; + + /* Don't use "FUNC_ENTER" macro, to avoid potential infinite recursion */ + PABLO_TRACE_ON(H5P_mask, ID_H5P_init_interface); + + /* Don't call this routine again... */ + interface_initialize = TRUE; + + /* Initialize the atom group for the file IDs */ + ret_value=H5Ainit_group(H5_DATASPACE,HDF5_DATASPACEID_HASHSIZE,H5P_RESERVED_ATOMS); + + FUNC_LEAVE(H5P_mask, ID_H5P_init_interface, ret_value); +} /* H5P_init_interface */ + +#ifdef NOT_YET +/*-------------------------------------------------------------------------- + NAME + H5Tcreate + PURPOSE + Create a new HDF5 data-type object + USAGE + hatom_t H5Tcreate(owner_id, type, name) + hatom_t owner_id; IN: Group/file which owns this object + hobjtype_t type; IN: Type of object to create + const char *name; IN: Name of the object + RETURNS + Returns ID (atom) on success, FAIL on failure + DESCRIPTION + This function actually creates the data-type object. +--------------------------------------------------------------------------*/ +hatom_t H5T_create(hatom_t owner_id, hobjtype_t type, const char *name) +{ + CONSTR(FUNC, "H5T_create"); /* for HERROR */ + h5_datatype_t *new_dt; /* new data-type object to create */ + hatom_t ret_value = SUCCEED; + + FUNC_ENTER(H5T_mask, ID_H5Tcreate, H5T_init_interface, FAIL); + + /* Clear errors and check args and all the boring stuff. */ + H5ECLEAR; + + /* Allocate space for the new data-type */ + if((new_dt=HDmalloc(sizeof(h5_datatype_t)))==NULL) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL); + + /* Initialize the datatype */ + new_dt->dt.base=0; /* No Default datatype */ + new_dt->name=HDstrdup(name); /* Make a copy of the datatype's name */ + new_dt->ci=NULL; /* Set the complex information to NULL */ + + /* Register the new datatype and get an ID for it */ + if((ret_value=H5Aregister_atom(H5_DATATYPE, (const VOIDP)new_dt))==FAIL) + HGOTO_ERROR(H5E_ATOM, H5E_CANTREGISTER, FAIL); + +done: + if(ret_value == FAIL) + { /* Error condition cleanup */ + + } /* end if */ + + /* Normal function cleanup */ + + FUNC_LEAVE(H5T_mask, ID_H5Tcreate, ret_value); +} /* end H5T_create() */ +#endif /* NOT_YET */ + +/*-------------------------------------------------------------------------- + NAME + H5Pnelem + PURPOSE + Return the number of elements in a dataspace + USAGE + uintn H5Pnelem(sid) + hatom_t sid; IN: Dataspace object to query + RETURNS + The number of elements in a dataspace on success, UFAIL on failure + DESCRIPTION + This function determines the number of dataset elements in a + dataspace. For example, a simple 3-dimensional dataspace with dimensions + 2, 3 and 4 would have 24 elements. + UFAIL is returned on an error, otherwise the number of elements is returned. +--------------------------------------------------------------------------*/ +uintn H5Pnelem(hatom_t sid) +{ + CONSTR(FUNC, "H5Pnelem"); /* for HERROR */ + uintn ret_value = UFAIL; + + FUNC_ENTER(H5P_mask, ID_H5Pnelem, H5P_init_interface, UFAIL); + + /* Clear errors and check args and all the boring stuff. */ + H5ECLEAR; + +#ifdef FINISH_THIS +#else /* FINISH_THIS */ + if(sid==H5P_SCALAR) + ret_value=1; +#endif /* FINISH_THIS */ + +done: + if(ret_value == UFAIL) + { /* Error condition cleanup */ + + } /* end if */ + + /* Normal function cleanup */ + + FUNC_LEAVE(H5P_mask, ID_H5Pnelem, ret_value); +} /* end H5Pnelem() */ + +#ifdef NOT_YET +/*-------------------------------------------------------------------------- + NAME + H5Trelease + PURPOSE + Release access to an HDF5 datatype object. + USAGE + herr_t H5Trelease(oid) + hatom_t oid; IN: Object to release access to + RETURNS + SUCCEED/FAIL + DESCRIPTION + This function releases a datatype from active use by a user. +--------------------------------------------------------------------------*/ +herr_t H5T_release(hatom_t oid) +{ + CONSTR(FUNC, "H5T_release"); /* for HERROR */ + h5_datatype_t *dt; /* new data-type object to create */ + herr_t ret_value = SUCCEED; + + FUNC_ENTER(H5T_mask, ID_H5Trelease, H5T_init_interface, FAIL); + + /* Clear errors and check args and all the boring stuff. */ + H5ECLEAR; + + /* Chuck the object! :-) */ + if((dt=H5Aremove_atom(oid))==NULL) + HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL); + if(dt->name!=NULL) + HDfree(dt->name); + if(dt->ci!=NULL) + { + } /* end if */ + HDfree(dt); + +done: + if(ret_value == FAIL) + { /* Error condition cleanup */ + + } /* end if */ + + /* Normal function cleanup */ + + FUNC_LEAVE(H5T_mask, ID_H5Trelease, ret_value); +} /* end H5T_release() */ +#endif /* NOT_YET */ + diff --git a/src/H5Pprivate.h b/src/H5Pprivate.h new file mode 100644 index 0000000..bad8702 --- /dev/null +++ b/src/H5Pprivate.h @@ -0,0 +1,30 @@ +/**************************************************************************** + * NCSA HDF * + * Software Development Group * + * National Center for Supercomputing Applications * + * University of Illinois at Urbana-Champaign * + * 605 E. Springfield, Champaign IL 61820 * + * * + * For conditions of distribution and use, see the accompanying * + * hdf/COPYING file. * + * * + ****************************************************************************/ + +/* $Id$ */ + +/* + * This file contains private information about the H5P module + */ + +#ifndef H5PPRIVATE_H +#define H5PPRIVATE_H + +#include "H5Pproto.h" +#define H5P_RESERVED_ATOMS 1 + +/*------------------_-- Local function prototypes ----------------------------*/ +static herr_t H5P_init_interface(void); + +#endif /* H5PPRIVATE_H */ + + diff --git a/src/H5Pproto.h b/src/H5Pproto.h new file mode 100644 index 0000000..218949a --- /dev/null +++ b/src/H5Pproto.h @@ -0,0 +1,39 @@ +/**************************************************************************** + * NCSA HDF * + * Software Development Group * + * National Center for Supercomputing Applications * + * University of Illinois at Urbana-Champaign * + * 605 E. Springfield, Champaign IL 61820 * + * * + * For conditions of distribution and use, see the accompanying * + * hdf/COPYING file. * + * * + ****************************************************************************/ + +/* $Id$ */ + +/* + * This file contains function prototypes for each exported function in the H5P module + */ + +#ifndef H5PPROTO_H +#define H5PPROTO_H + +/* Define atomic datatypes */ +#define H5P_SCALAR MAKE_ATOM(H5_DATASPACE,0) + + +#if defined c_plusplus || defined __cplusplus +extern "C" +{ +#endif /* c_plusplus || __cplusplus */ + +/* Functions in H5P.c */ +uintn H5Pnelem(hatom_t dim_id); + +#if defined c_plusplus || defined __cplusplus +} +#endif /* c_plusplus || __cplusplus */ + +#endif /* H5PPROTO_H */ + diff --git a/src/H5T.c b/src/H5T.c new file mode 100644 index 0000000..f7bb155 --- /dev/null +++ b/src/H5T.c @@ -0,0 +1,662 @@ +/**************************************************************************** +* NCSA HDF * +* Software Development Group * +* National Center for Supercomputing Applications * +* University of Illinois at Urbana-Champaign * +* 605 E. Springfield, Champaign IL 61820 * +* * +* For conditions of distribution and use, see the accompanying * +* hdf/COPYING file. * +* * +****************************************************************************/ + +#ifdef RCSID +static char RcsId[] = "@(#)$Revision$"; +#endif + +/* $Id$ */ + +/*LINTLIBRARY */ +/*+ + FILE + H5T.c + HDF5 Data-type routines + + EXPORTED ROUTINES + H5Tget_num_fields -- Get the number of fields in a compound datatype + H5Tis_field_atomic -- Check if a field is atomic + H5Tis_atomic -- Check if a datatype is atomic + H5Tset_type -- Set the base type of a user-defined datatype + H5Tadd_field -- Add a field to a compound datatype + H5Tsize -- Determine the size of a datatype + + LIBRARY-SCOPED ROUTINES + H5T_create -- (Meta-Object) Create a datatype + H5T_release -- (Meta-Object) Release access to a datatype + + LOCAL ROUTINES + H5T_init_interface -- initialize the interface + + */ + +#include "hdf5.h" +#include "H5private.h" /* Generic Functions */ +#include "H5Tprivate.h" /* Data-type functions */ + +/*--------------------- Locally scoped variables -----------------------------*/ + +/* Whether we've installed the library termination function yet for this interface */ +static intn interface_initialize = FALSE; + +/*------------------_-- Local function prototypes ----------------------------*/ +static herr_t H5T_init_interface(void); + +/*-------------------------------------------------------------------------- +NAME + H5T_init_interface -- Initialize interface-specific information +USAGE + herr_t H5T_init_interface() + +RETURNS + SUCCEED/FAIL +DESCRIPTION + Initializes any interface-specific data or routines. + +--------------------------------------------------------------------------*/ +static herr_t H5T_init_interface(void) +{ +#ifdef LATER + CONSTR(FUNC, "H5T_init_interface"); /* For HERROR */ +#endif /* LATER */ + herr_t ret_value = SUCCEED; + + /* Don't use "FUNC_ENTER" macro, to avoid potential infinite recursion */ + PABLO_TRACE_ON(H5T_mask, ID_H5T_init_interface); + + /* Don't call this routine again... */ + interface_initialize = TRUE; + + /* Initialize the atom group for the file IDs */ + ret_value=H5Ainit_group(H5_DATATYPE,HDF5_DATATYPEID_HASHSIZE,H5T_RESERVED_ATOMS); + + FUNC_LEAVE(H5T_mask, ID_H5T_init_interface, ret_value); +} /* H5T_init_interface */ + +/*-------------------------------------------------------------------------- + NAME + H5T_create + PURPOSE + Create a new HDF5 data-type object + USAGE + hatom_t H5T_create(owner_id, type, name) + hatom_t owner_id; IN: Group/file which owns this object + hobjtype_t type; IN: Type of object to create + const char *name; IN: Name of the object + RETURNS + Returns ID (atom) on success, FAIL on failure + DESCRIPTION + This function actually creates the data-type object. +--------------------------------------------------------------------------*/ +hatom_t H5T_create(hatom_t owner_id, hobjtype_t type, const char *name) +{ + CONSTR(FUNC, "H5T_create"); /* for HERROR */ + h5_datatype_t *new_dt; /* new data-type object to create */ + hatom_t ret_value = SUCCEED; + + FUNC_ENTER(H5T_mask, ID_H5T_create, H5T_init_interface, FAIL); + + /* Clear errors and check args and all the boring stuff. */ + H5ECLEAR; + + /* Allocate space for the new data-type */ + if((new_dt=HDmalloc(sizeof(h5_datatype_t)))==NULL) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL); + + /* Initialize the datatype */ + new_dt->dt.base=0; /* No Default datatype */ + new_dt->name=HDstrdup(name); /* Make a copy of the datatype's name */ + new_dt->ci=NULL; /* Set the complex information to NULL */ + + /* Register the new datatype and get an ID for it */ + if((ret_value=H5Aregister_atom(H5_DATATYPE, (const VOIDP)new_dt))==FAIL) + HGOTO_ERROR(H5E_ATOM, H5E_CANTREGISTER, FAIL); + +done: + if(ret_value == FAIL) + { /* Error condition cleanup */ + + } /* end if */ + + /* Normal function cleanup */ + + FUNC_LEAVE(H5T_mask, ID_H5T_create, ret_value); +} /* end H5T_create() */ + +/*-------------------------------------------------------------------------- + NAME + H5Tget_num_fields + PURPOSE + Return the number of fields in a compound datatype + USAGE + uint32 H5Tget_num_fields(tid) + hatom_t tid; IN: Datatype object to query + RETURNS + The number of fields in a compound datatype on success, UFAIL on failure + DESCRIPTION + This function checks the number of fields in a compound user-defined + datatype. UFAIL is returned on an error or if an atomic datatype is + queried, otherwise the number of fields is returned. +--------------------------------------------------------------------------*/ +uint32 H5Tget_num_fields(hatom_t tid) +{ + CONSTR(FUNC, "H5Tget_num_fields"); /* for HERROR */ + h5_datatype_t *dt; /* new data-type object to create */ + uint32 ret_value = UFAIL; + + FUNC_ENTER(H5T_mask, ID_H5Tget_num_fields, H5T_init_interface, UFAIL); + + /* Clear errors and check args and all the boring stuff. */ + H5ECLEAR; + + /* Go get the object */ + if((dt=H5Aatom_object(tid))==NULL) + HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL); + + /* Check the base type of the datatype */ + if(H5T_COMPOUND!=dt->dt.base) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL); + + /* Check if the compound information has been initialized */ + if(NULL==dt->ci) + HGOTO_ERROR(H5E_INTERNAL, H5E_UNINITIALIZED, FAIL); + + /* Grab the number of fields */ + ret_value=dt->ci->n; + +done: + if(ret_value == UFAIL) + { /* Error condition cleanup */ + + } /* end if */ + + /* Normal function cleanup */ + + FUNC_LEAVE(H5T_mask, ID_H5Tget_num_fields, ret_value); +} /* end H5Tget_num_fields() */ + +/*-------------------------------------------------------------------------- + NAME + H5Tis_field_atomic + PURPOSE + Check if a field in a compound datatype is atomic + USAGE + hbool_t H5Tis_field_atomic(tid, fidx) + hatom_t tid; IN: Datatype object to query + uintn fidx; IN: Index of the field to query + RETURNS + BFAIL/BTRUE/BFALSE + DESCRIPTION + This function checks the basic type of field in a user-defined datatype. + BTRUE is returned if the datatype is atomic (i.e. not compound), BFALSE is + returned if the datatype is compound, BFAIL on error. +--------------------------------------------------------------------------*/ +hbool_t H5Tis_field_atomic(hatom_t tid, uintn fidx) +{ + CONSTR(FUNC, "H5Tis_field_atomic"); /* for HERROR */ + h5_datatype_t *dt; /* new data-type object to create */ + hbool_t ret_value = BTRUE; + + FUNC_ENTER(H5T_mask, ID_H5Tis_field_atomic, H5T_init_interface, BFAIL); + + /* Clear errors and check args and all the boring stuff. */ + H5ECLEAR; + + /* Go get the object */ + if((dt=H5Aatom_object(tid))==NULL) + HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL); + + /* Check the base type of the datatype */ + if(H5T_COMPOUND!=dt->dt.base) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL); + + /* Check if the compound information has been initialized */ + if(NULL==dt->ci) + HGOTO_ERROR(H5E_INTERNAL, H5E_UNINITIALIZED, FAIL); + + /* Check if the field is valid*/ + if(fidx>=dt->ci->n) + HGOTO_ERROR(H5E_INTERNAL, H5E_BADRANGE, FAIL); + + /* Check the base type of the field */ + if(H5T_COMPOUND==dt->ci->flist[fidx].dt.base || H5P_SCALAR!=dt->ci->flist[fidx].dim_id) + ret_value=BFALSE; + +done: + if(ret_value == BFAIL) + { /* Error condition cleanup */ + + } /* end if */ + + /* Normal function cleanup */ + + FUNC_LEAVE(H5T_mask, ID_H5Tis_field_atomic, ret_value); +} /* end H5Tis_field_atomic() */ + +/*-------------------------------------------------------------------------- + NAME + H5Tis_atomic + PURPOSE + Check if a datatype is atomic + USAGE + hbool_t H5Tis_atomic(tid) + hatom_t tid; IN: Datatype object to query + RETURNS + BFAIL/BTRUE/BFALSE + DESCRIPTION + This function checks the basic type of a user-defined datatype. BTRUE + is returned if the datatype is atomic (i.e. not compound), BFALSE is + returned if the datatype is compound, BFAIL on error. +--------------------------------------------------------------------------*/ +hbool_t H5Tis_atomic(hatom_t tid) +{ + CONSTR(FUNC, "H5Tis_atomic"); /* for HERROR */ + h5_datatype_t *dt; /* new data-type object to create */ + hbool_t ret_value = BTRUE; + + FUNC_ENTER(H5T_mask, ID_H5Tis_atomic, H5T_init_interface, BFAIL); + + /* Clear errors and check args and all the boring stuff. */ + H5ECLEAR; + + /* Go get the object */ + if((dt=H5Aatom_object(tid))==NULL) + HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL); + + /* Check the base type of the datatype */ + if(H5T_COMPOUND==dt->dt.base) + ret_value=BFALSE; + +done: + if(ret_value == BFAIL) + { /* Error condition cleanup */ + + } /* end if */ + + /* Normal function cleanup */ + + FUNC_LEAVE(H5T_mask, ID_H5Tis_atomic, ret_value); +} /* end H5Tis_atomic() */ + +/*-------------------------------------------------------------------------- + NAME + H5Tset_type + PURPOSE + Set the base type of a user-defined datatype + USAGE + herr_t H5Tset_type(tid, base, len, arch) + hatom_t tid; IN: Datatype object to modify + hatom_t base; IN: Base type to set the datatype to + uint8 len; IN: Length of the object in bytes + uint8 arch; IN: Architecture format to store type with + RETURNS + SUCCEED/FAIL + DESCRIPTION + This function sets the basic type of a user-defined datatype. Each + datatype is either an atomic type (i.e. has no further divisions of the + type) or is a compound type (like a C structure). If the datatype is set + to a compound type, the 'len' argument is not used. +--------------------------------------------------------------------------*/ +herr_t H5Tset_type(hatom_t tid,hatom_t base,uint8 len,uint8 arch) +{ + CONSTR(FUNC, "H5Tset_type"); /* for HERROR */ + h5_datatype_t *dt; /* new data-type object to create */ + herr_t ret_value = SUCCEED; + + FUNC_ENTER(H5T_mask, ID_H5Tset_type, H5T_init_interface, FAIL); + + /* Clear errors and check args and all the boring stuff. */ + H5ECLEAR; + if(base<H5T_CHAR || base>H5T_COMPOUND) + HGOTO_ERROR(H5E_ARGS, H5E_BADRANGE, FAIL); + + /* Go get the object */ + if((dt=H5Aatom_object(tid))==NULL) + HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL); + if(dt->dt.base!=0) + HGOTO_ERROR(H5E_FUNC, H5E_ALREADYINIT, FAIL); + + /* Set the basic datatype information */ + dt->dt.base=base; + dt->dt.len=len; + dt->dt.arch=arch; + +done: + if(ret_value == FAIL) + { /* Error condition cleanup */ + + } /* end if */ + + /* Normal function cleanup */ + + FUNC_LEAVE(H5T_mask, ID_H5Tset_type, ret_value); +} /* end H5Tset_type() */ + +/*-------------------------------------------------------------------------- + NAME + H5Tadd_field + PURPOSE + Add a field to a compound datatype + USAGE + herr_t H5Tadd_field(tid, name, base, len, arch, space) + hatom_t tid; IN: Datatype object to query + const char *fidx; IN: Field name + hatom_t base; IN: Field's base type, either an atom ID for + an existing compound type, or an atomic + base type + uint8 len; IN: Length of an atomic base type + uint8 arch; IN: Architecture format of an atomic base type + hatom_t space; IN: The dimensionality of the field to add + RETURNS + SUCCEED/FAIL + DESCRIPTION + This function adds a field to a user-defined compound datatype. The + field can either be a base/len/arch triplet or an existing compound type + (passed in the base argument). The space parameter is either H5P_SCALAR + (to indicate a scalar field) or the atom of a datatype for more complex + dimensionality fields. +--------------------------------------------------------------------------*/ +herr_t H5Tadd_field(hatom_t tid, const char *name, hatom_t base, uint8 len, uint8 arch, hatom_t space) +{ + CONSTR(FUNC, "H5Tadd_field"); /* for HERROR */ + h5_field_info_t *new_field; /* pointer to new field to add */ + h5_datatype_t *dt; /* data-type object to manipulate */ + herr_t ret_value = SUCCEED; + + FUNC_ENTER(H5T_mask, ID_H5Tadd_field, H5T_init_interface, FAIL); + + /* Clear errors and check args and all the boring stuff. */ + H5ECLEAR; + + /* Go get the object */ + if((dt=H5Aatom_object(tid))==NULL) + HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL); + + /* Check the base type of the datatype */ + if(H5T_COMPOUND!=dt->dt.base) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL); + + /* Check if the compound information has been initialized */ + if(NULL==dt->ci) + { + if(NULL==(dt->ci=HDmalloc(sizeof(h5_compound_info_t)))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL); + dt->ci->n=0; /* Set the number of fields to 0 */ + dt->ci->mem_size=0; /* Set the size of the structure */ + dt->ci->disk_size=0; /* Set the size of the structure */ + dt->ci->flist=NULL; /* No field information yet */ + } /* end if */ + + if(NULL==(new_field=HDrealloc(dt->ci->flist,(dt->ci->n+1)*sizeof(h5_field_info_t)))) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL); + dt->ci->n++; /* increment the number of fields */ + dt->ci->flist=new_field; /* save the pointer to the increased array of fields */ + new_field=&dt->ci->flist[dt->ci->n-1]; /* get a "convenience" pointer to the new field */ + + new_field->name=HDstrdup(name); /* copy the name */ + new_field->name_off=0; /* name isn't stored yet */ + new_field->struct_off=dt->ci->disk_size; /* Set the offset of the field on disk */ + new_field->dim_id=H5Mcopy(space); /* Make a copy of the dimension space for the field */ + if((H5Ais_reserved(base)==BTRUE) && base!=H5T_COMPOUND) /* Check if this is a "simple" datatype */ + { + new_field->dt.base=base; /* Make a copy of the datatype for the field */ + new_field->dt.len=len; + new_field->dt.arch=arch; + } /* end if */ + else + { + new_field->dt.base=H5Mcopy(base); /* Make a copy of the datatype for the field */ + new_field->dt.len=H5Tsize(base,len,arch,BTRUE); + new_field->dt.arch=arch; + } /* end else */ + +done: + if(ret_value == FAIL) + { /* Error condition cleanup */ + + } /* end if */ + + /* Normal function cleanup */ + + FUNC_LEAVE(H5T_mask, ID_H5Tadd_field, ret_value); +} /* end H5Tadd_field() */ + +/*-------------------------------------------------------------------------- + NAME + H5Tsize + PURPOSE + Determine the size of a datatype + USAGE + uintn H5Tsize(tid, mem_flag) + hatom_t tid; IN: Datatype object to query + hbool_t mem_flag; IN: Whether the memory or disk size is desired + RETURNS + The size of the datatype on success or UFAIL on failure. + DESCRIPTION + Ths function returns the size of the datatype in bytes as it is stored + on disk or in memory, depending on the mem_flag. Setting the mem_flag to + BTRUE returns the size in memory, BFALSE returns the size on disk. +--------------------------------------------------------------------------*/ +uintn H5Tsize(hatom_t tid, uint8 len, uint8 arch, hbool_t mem_flag) +{ + CONSTR(FUNC, "H5Tsize"); /* for HERROR */ + uintn ret_value = UFAIL; + + FUNC_ENTER(H5T_mask, ID_H5Tsize, H5T_init_interface, UFAIL); + + /* Clear errors and check args and all the boring stuff. */ + H5ECLEAR; + + if((H5Ais_reserved(tid)==BTRUE) && tid!=H5T_COMPOUND) /* Check if this is a "simple" datatype */ + { + switch(tid) + { + case H5T_CHAR: + case H5T_INT: + case H5T_FLOAT: /* All three of thes types use the length as the number of bytes */ + ret_value=len; + break; + + case H5T_DATE: + ret_value=8; /* Number of characters for ISO 8601 format */ + break; + + case H5T_TIME: + ret_value=6; /* Number of characters for ISO 8601 format */ + break; + + case H5T_SPTR: + HGOTO_ERROR(H5E_INTERNAL, H5E_UNSUPPORTED, UFAIL); + break; + + case H5T_PPTR: + HGOTO_ERROR(H5E_INTERNAL, H5E_UNSUPPORTED, UFAIL); + break; + + default: + HGOTO_ERROR(H5E_ARGS, H5E_BADRANGE, UFAIL); + } /* end switch */ + } /* end if */ + else + { + if(tid==H5T_COMPOUND) + { + intn i; /* local counting variable */ + h5_datatype_t *dt; /* datatype pointer */ + + /* Go get the object */ + if((dt=H5Aatom_object(tid))==NULL) + HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL); + + /* Check the base type of the datatype */ + if(H5T_COMPOUND!=dt->dt.base) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL); + + /* Check if the compound information has been initialized */ + if(NULL==dt->ci) + HGOTO_ERROR(H5E_INTERNAL, H5E_UNINITIALIZED, FAIL); + + /* Grab the number of fields */ + for(i=0; i<=dt->ci->n; i++) + ret_value+=H5Tsize(dt->ci->flist[i].dt.base, dt->ci->flist[i].dt.len, + dt->ci->flist[i].dt.arch,mem_flag)*H5Pnelem(dt->ci->flist[i].dim_id); + } /* end if */ + } /* end else */ + +done: + if(ret_value == UFAIL) + { /* Error condition cleanup */ + + } /* end if */ + + /* Normal function cleanup */ + + FUNC_LEAVE(H5T_mask, ID_H5Tsize, ret_value); +} /* end H5Tsize() */ + +/*-------------------------------------------------------------------------- + NAME + H5Tget_fields + PURPOSE + Determine the size of a datatype + USAGE + herr_t H5Tget_fields(tid, field_list) + hatom_t tid; IN: Datatype object to query + hoid_t *field_list; IN: Array to store list of fields + RETURNS + SUCCEED/FAIL + DESCRIPTION + Ths function returns the size of the datatype in bytes as it is stored + on disk or in memory, depending on the mem_flag. Setting the mem_flag to + BTRUE returns the size in memory, BFALSE returns the size on disk. +--------------------------------------------------------------------------*/ +herr_t H5Tget_fields(hatom_t tid, hoid_t *field_list) +{ + CONSTR(FUNC, "H5Tsize"); /* for HERROR */ + uintn ret_value = UFAIL; + + FUNC_ENTER(H5T_mask, ID_H5Tsize, H5T_init_interface, UFAIL); + + /* Clear errors and check args and all the boring stuff. */ + H5ECLEAR; + + if((H5Ais_reserved(tid)==BTRUE) && tid!=H5T_COMPOUND) /* Check if this is a "simple" datatype */ + { + switch(tid) + { + case H5T_CHAR: + case H5T_INT: + case H5T_FLOAT: /* All three of thes types use the length as the number of bytes */ + ret_value=len; + break; + + case H5T_DATE: + ret_value=8; /* Number of characters for ISO 8601 format */ + break; + + case H5T_TIME: + ret_value=6; /* Number of characters for ISO 8601 format */ + break; + + case H5T_SPTR: + HGOTO_ERROR(H5E_INTERNAL, H5E_UNSUPPORTED, UFAIL); + break; + + case H5T_PPTR: + HGOTO_ERROR(H5E_INTERNAL, H5E_UNSUPPORTED, UFAIL); + break; + + default: + HGOTO_ERROR(H5E_ARGS, H5E_BADRANGE, UFAIL); + } /* end switch */ + } /* end if */ + else + { + if(tid==H5T_COMPOUND) + { + intn i; /* local counting variable */ + h5_datatype_t *dt; /* datatype pointer */ + + /* Go get the object */ + if((dt=H5Aatom_object(tid))==NULL) + HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL); + + /* Check the base type of the datatype */ + if(H5T_COMPOUND!=dt->dt.base) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL); + + /* Check if the compound information has been initialized */ + if(NULL==dt->ci) + HGOTO_ERROR(H5E_INTERNAL, H5E_UNINITIALIZED, FAIL); + + /* Grab the number of fields */ + for(i=0; i<=dt->ci->n; i++) + ret_value+=H5Tsize(dt->ci->flist[i].dt.base, dt->ci->flist[i].dt.len, + dt->ci->flist[i].dt.arch,mem_flag)*H5Pnelem(dt->ci->flist[i].dim_id); + } /* end if */ + } /* end else */ + +done: + if(ret_value == UFAIL) + { /* Error condition cleanup */ + + } /* end if */ + + /* Normal function cleanup */ + + FUNC_LEAVE(H5T_mask, ID_H5Tsize, ret_value); +} /* end H5Tsize() */ + +/*-------------------------------------------------------------------------- + NAME + H5T_release + PURPOSE + Release access to an HDF5 datatype object. + USAGE + herr_t H5T_release(oid) + hatom_t oid; IN: Object to release access to + RETURNS + SUCCEED/FAIL + DESCRIPTION + This function releases a datatype from active use by a user. +--------------------------------------------------------------------------*/ +herr_t H5T_release(hatom_t oid) +{ + CONSTR(FUNC, "H5T_release"); /* for HERROR */ + h5_datatype_t *dt; /* new data-type object to create */ + herr_t ret_value = SUCCEED; + + FUNC_ENTER(H5T_mask, ID_H5T_release, H5T_init_interface, FAIL); + + /* Clear errors and check args and all the boring stuff. */ + H5ECLEAR; + + /* Chuck the object! :-) */ + if((dt=H5Aremove_atom(oid))==NULL) + HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL); + if(dt->name!=NULL) + HDfree(dt->name); + if(dt->ci!=NULL) + { + } /* end if */ + HDfree(dt); + +done: + if(ret_value == FAIL) + { /* Error condition cleanup */ + + } /* end if */ + + /* Normal function cleanup */ + + FUNC_LEAVE(H5T_mask, ID_H5T_release, ret_value); +} /* end H5T_release() */ + diff --git a/src/H5Tprivate.h b/src/H5Tprivate.h new file mode 100644 index 0000000..31b2e74 --- /dev/null +++ b/src/H5Tprivate.h @@ -0,0 +1,50 @@ +/**************************************************************************** + * NCSA HDF * + * Software Development Group * + * National Center for Supercomputing Applications * + * University of Illinois at Urbana-Champaign * + * 605 E. Springfield, Champaign IL 61820 * + * * + * For conditions of distribution and use, see the accompanying * + * hdf/COPYING file. * + * * + ****************************************************************************/ + +/* $Id$ */ + +/* + * This file contains private information about the H5T module + */ + +#ifndef H5TPRIVATE_H +#define H5TPRIVATE_H + +#include "H5Tproto.h" +#define H5T_RESERVED_ATOMS 8 + +/* Structure for storing information about a field in a compound datatype */ +typedef struct { + char *name; /* Name of the field */ + uintn name_off; /* Offset of name in global small-data heap */ + uintn struct_off; /* Offset of field within structure */ + h5_atomic_type_t dt; /* Datatype of the field */ + hatom_t dim_id; /* dimensionality ID of the field */ + } h5_field_info_t; + +/* Structure for storing information about a compound datatype */ +typedef struct { + uintn n; /* Number of fields */ + uintn mem_size; /* Size of the compound structure in memory */ + uintn disk_size; /* Size of the compound structure on disk */ + h5_field_info_t *flist; /* List of fields in the compound object */ + } h5_compound_info_t; + +/* Structure for storing information any datatype */ +typedef struct { + h5_atomic_type_t dt; /* Atomic type of this object */ + char *name; /* Name of datatype */ + h5_compound_info_t *ci; /* Information for compound datatypes */ + } h5_datatype_t; + +#endif /* H5TPRIVATE_H */ + diff --git a/src/H5Tproto.h b/src/H5Tproto.h new file mode 100644 index 0000000..5e32b0f --- /dev/null +++ b/src/H5Tproto.h @@ -0,0 +1,57 @@ +/**************************************************************************** + * NCSA HDF * + * Software Development Group * + * National Center for Supercomputing Applications * + * University of Illinois at Urbana-Champaign * + * 605 E. Springfield, Champaign IL 61820 * + * * + * For conditions of distribution and use, see the accompanying * + * hdf/COPYING file. * + * * + ****************************************************************************/ + +/* $Id$ */ + +/* + * This file contains function prototypes for each exported function in the H5T module + */ + +#ifndef H5TPROTO_H +#define H5TPROTO_H + +/* Define atomic datatypes */ +#define H5T_CHAR MAKE_ATOM(H5_DATATYPE,0) +#define H5T_INT MAKE_ATOM(H5_DATATYPE,1) +#define H5T_FLOAT MAKE_ATOM(H5_DATATYPE,2) +#define H5T_DATE MAKE_ATOM(H5_DATATYPE,3) +#define H5T_TIME MAKE_ATOM(H5_DATATYPE,4) +#define H5T_SPTR MAKE_ATOM(H5_DATATYPE,5) +#define H5T_PPTR MAKE_ATOM(H5_DATATYPE,6) +#define H5T_COMPOUND MAKE_ATOM(H5_DATATYPE,7) + +typedef struct { + hatom_t base; /* Basic datatype */ + uint8 len; /* Length of base-type, in bytes */ + uint8 arch; /* Architecture of the base-type */ + } h5_atomic_type_t; + +#if defined c_plusplus || defined __cplusplus +extern "C" +{ +#endif /* c_plusplus || __cplusplus */ + +/* Functions in H5T.c */ +hatom_t H5T_create(hatom_t owner_id, hobjtype_t type, const char *name); +uint32 H5Tget_num_fields(hatom_t tid); +hbool_t H5Tis_field_atomic(hatom_t tid,uintn fidx); +hbool_t H5Tis_atomic(hatom_t tid); +herr_t H5Tset_type(hatom_t tid,hatom_t base,uint8 len,uint8 arch); +uintn H5Tsize(hatom_t tid, uint8 len, uint8 arch, hbool_t mem_flag); +herr_t H5T_release(hatom_t oid); + +#if defined c_plusplus || defined __cplusplus +} +#endif /* c_plusplus || __cplusplus */ + +#endif /* H5TPROTO_H */ + diff --git a/src/H5private.h b/src/H5private.h new file mode 100644 index 0000000..62e7e6c --- /dev/null +++ b/src/H5private.h @@ -0,0 +1,30 @@ +/**************************************************************************** + * NCSA HDF * + * Software Development Group * + * National Center for Supercomputing Applications * + * University of Illinois at Urbana-Champaign * + * 605 E. Springfield, Champaign IL 61820 * + * * + * For conditions of distribution and use, see the accompanying * + * hdf/COPYING file. * + * * + ****************************************************************************/ + +/* $Id$ */ + +/* + * This file contains macros & private information for general HDF5 functions + */ + +#ifndef H5PRIVATE_H +#define H5PRIVATE_H + +#include "H5proto.h" /* Include Public Definitions */ + +/* Private functions, not part of the publicly documented API */ +herr_t H5_init_library(void); +void H5_term_library(void); +herr_t H5_init_thread(void); + +#endif /* H5PRIVATE_H */ + diff --git a/src/H5proto.h b/src/H5proto.h new file mode 100644 index 0000000..f425c76 --- /dev/null +++ b/src/H5proto.h @@ -0,0 +1,35 @@ +/**************************************************************************** + * NCSA HDF * + * Software Development Group * + * National Center for Supercomputing Applications * + * University of Illinois at Urbana-Champaign * + * 605 E. Springfield, Champaign IL 61820 * + * * + * For conditions of distribution and use, see the accompanying * + * hdf/COPYING file. * + * * + ****************************************************************************/ + +/* $Id$ */ + +/* + * This file contains function prototypes for each exported function in the H5 module + */ + +#ifndef H5PROTO_H +#define H5PROTO_H + +#if defined c_plusplus || defined __cplusplus +extern "C" +{ +#endif /* c_plusplus || __cplusplus */ + +/* Functions in H5.c */ +herr_t H5dont_atexit(void); +herr_t H5version(uintn *majnum, uintn *minnum, uintn *relnum, uintn *patnum); + +#if defined c_plusplus || defined __cplusplus +} +#endif /* c_plusplus || __cplusplus */ + +#endif /* H5PROTO_H */ diff --git a/src/Makefile b/src/Makefile new file mode 100644 index 0000000..0a710ee --- /dev/null +++ b/src/Makefile @@ -0,0 +1,92 @@ +### Name of target +TARGET = libhdf5.a + +# +# PART 2: various choices +# + +### -DDEBUG Debugging options on +DEFS = + +# +# PART 3: hardware dependend +# + +### CC entry: name and arguments for the compiler (also for linking) +### MACHINE entry: defines used for compiling (not for linking) +### LIBS: defines used for linking +MACHINE = +CC=gcc -O +LIBS = + +################################################ +## no changes required below this line ## +################################################ + +CFLAGS = -c $(MACHINE) $(DEFS) + +INCL = hdf5.h + +OBJ = H5.o H5E.o H5A.o H5F.o H5C.o H5M.o H5AC.o H5B.o H5MM.o H5MF.o H5T.o \ + H5Gnode.o H5H.o H5G.o H5P.o + +$(TARGET): $(OBJ) + $(AR) $(ARFLAGS) $(TARGET) $(OBJ) + $(RANLIB) $(TARGET) + +all test: $(TARGET) + +debug: $(OBJ) + $(AR) $(ARFLAGS) $(TARGET) $(OBJ) + $(RANLIB) $(TARGET) + +clean: + -rm -f *.o core $(TARGET) + -rm -f *.bak + +########################################################################### + +H5.o: H5.c $(INCL) H5private.h H5proto.h + $(CC) $(CFLAGS) H5.c + +H5E.o: H5E.c $(INCL) H5Eprivate.h H5Eproto.h + $(CC) $(CFLAGS) H5E.c + +H5F.o: H5F.c $(INCL) H5Fprivate.h H5Fproto.h + $(CC) $(CFLAGS) H5F.c + +H5C.o: H5C.c $(INCL) H5Cprivate.h H5Cproto.h + $(CC) $(CFLAGS) H5C.c + +H5M.o: H5M.c $(INCL) H5Mprivate.h H5Mproto.h + $(CC) $(CFLAGS) H5M.c + +H5A.o: H5A.c $(INCL) H5Aprivate.h H5Aproto.h + $(CC) $(CFLAGS) H5A.c + +H5AC.o: H5AC.c $(INCL) H5ACprivate.h H5ACproto.h + $(CC) $(CFLAGS) H5AC.c + +H5B.o: H5B.c $(INCL) H5Bprivate.h H5Bproto.h + $(CC) $(CFLAGS) H5B.c + +H5MM.o: H5MM.c $(INCL) H5MMprivate.h H5MMproto.h + $(CC) $(CFLAGS) H5MM.c + +H5MF.o: H5MF.c $(INCL) H5MFprivate.h H5MFproto.h + $(CC) $(CFLAGS) H5MF.c + +H5T.o: H5T.c $(INCL) H5Tprivate.h H5Tproto.h + $(CC) $(CFLAGS) H5T.c + +H5Gnode.o: H5Gnode.c $(INCL) H5Gprivate.h H5Gproto.h + $(CC) $(CFLAGS) H5Gnode.c + +H5H.o: H5H.c $(INCL) H5Hprivate.h H5Hproto.h + $(CC) $(CFLAGS) H5H.c + +H5G.o: H5G.c $(INCL) H5Gprivate.h H5Gproto.h + $(CC) $(CFLAGS) H5G.c + +H5P.o: H5P.c $(INCL) H5Pprivate.h H5Pproto.h + $(CC) $(CFLAGS) H5P.c diff --git a/src/h5oplat.h b/src/h5oplat.h new file mode 100644 index 0000000..eb8627f --- /dev/null +++ b/src/h5oplat.h @@ -0,0 +1,555 @@ +/**************************************************************************** + * NCSA HDF * + * Software Development Group * + * National Center for Supercomputing Applications * + * University of Illinois at Urbana-Champaign * + * 605 E. Springfield, Champaign IL 61820 * + * * + * For conditions of distribution and use, see the accompanying * + * hdf/COPYING file. * + * * + ****************************************************************************/ + +/* $Id$ */ + +#ifndef H5OPLAT_H +#define H5OPLAT_H + +/* + * This file contains machine definitions for older architectures which once + * were working, but haven't been tested in a long-time. If you wish to use + * and test an architecture from this file, move the entire machine's + * definition from this file into the hdf5plat.h file and make certain to + * delete the entry in this file. -QAK + */ + +/*------------------------------------------------------------------------- + * Define options for each platform + *-------------------------------------------------------------------------*/ + +#if (defined(SUN) || defined(sun) || defined(__sun__) || defined(__SUNPRO_C)) & !defined(__i386) +#ifdef __STDC__ +#define ANSISUN +#else /* __STDC__ */ +#define KNRSUN +#endif /* __STDC__ */ +#endif /* SUN || sun */ + +/* + * CPU: Sparc (possibly Motorola 68K?) + * OS: Solaris 1.x (?), SunOS 4.x + */ +#if defined(KNRSUN) + +#if !defined(SUN) +#define SUN +#endif + +#ifdef GOT_MACHINE +If you get an error on this line more than one machine type has been defined. +Please check your Makefile. +#endif +#define GOT_MACHINE + +/* Extra include files required for this platform */ +# define BSD +#define DUMBCC /* because it is. for later use in macros */ +#ifndef __GNUC__ +#include <memory.h> +#endif /* __GNUC__ */ +#include <unistd.h> +#include <sys/file.h> /* for unbuffered i/o stuff */ +#include <sys/stat.h> + +/* Set machine byte-format */ +#define DF_MT DFMT_SUN + +/* Define portable variable types */ +typedef void VOID; +typedef char *VOIDP; +typedef char *_fcd; /* Fortran character descriptor type */ +typedef char char8; +typedef unsigned char uchar8; +typedef char int8; +typedef unsigned char uint8; +typedef short int int16; +typedef unsigned short int uint16; +typedef long int int32; +typedef unsigned long int uint32; +typedef int intn; +typedef unsigned int uintn; +typedef int intf; /* size of INTEGERs in Fortran compiler */ +typedef float float32; +typedef double float64; + +/* Fortran compatibility macros */ +#define FNAME_POST_UNDERSCORE /* Fortran function names require trailing underscore */ +#define _fcdtocp(desc) (desc) /* Macro to convert from Fortran character descriptor to C 'char *' */ + +/* Choose the I/O package to use when interacting with the file */ +#ifdef HAVE_FMPOOL +#define FILELIB PAGEBUFIO /* enable page buffering */ +#else +#define FILELIB POSIXBUFIO +#endif + +/* JPEG #define's - Look in the JPEG docs before changing - (Q) */ + +/* Determine the memory manager we are going to use. Valid values are: */ +/* MEM_DOS, MEM_ANSI, MEM_NAME, MEM_NOBS. See the JPEG docs for details on */ +/* what each does */ +#define JMEMSYS MEM_ANSI + +#ifdef __GNUC__ +#define HAVE_STDC +#define INCLUDES_ARE_ANSI +#endif + +#endif /* SUN */ + +/* + * CPU: Vax & Alpha (yeah, right! this definition is probably not really that portable! -QAK ) + * OS: VMS, OpenVMS + */ +#if defined(VMS) || defined(vms) + +#ifdef GOT_MACHINE +If you get an error on this line more than one machine type has been defined. +Please check your Makefile. +#endif +#define GOT_MACHINE 1 + +/* Extra include files required for this platform */ +#include <file.h> /* for unbuffered i/o stuff */ +#include <sys/stat.h> + +/* Set machine byte-format */ +#define DF_MT DFMT_VAX + +/* Define portable variable types */ +typedef void VOID; +typedef void *VOIDP; +typedef char *_fcd; /* Fortran character descriptor type */ +typedef char char8; +typedef unsigned char uchar8; +typedef char int8; +typedef unsigned char uint8; +typedef short int int16; +typedef unsigned short int uint16; +#ifdef __alpha +typedef int int32; +typedef unsigned int uint32; +#else +typedef long int int32; +typedef unsigned long int uint32; +#endif +typedef int intn; +typedef unsigned int uintn; +typedef float float32; +typedef double float64; +typedef int intf; /* size of INTEGERs in Fortran compiler */ + +/* Fortran compatibility macros */ +#define DF_CAPFNAMES /* fortran names are in all caps */ +#define _fcdtocp(desc) ((char *) *((char **) &desc[4])) /* Macro to convert from Fortran character descriptor to C 'char *' */ + +/* Choose the I/O package to use when interacting with the file */ +#define FILELIB POSIXBUFIO + +/* + Redef a couple of C routine names to avoid conflicts + since the VMS link command is case-insensitive +*/ +#include "dfivms.h" + + +/* JPEG #define's - Look in the JPEG docs before changing - (Q) */ + +/* Determine the memory manager we are going to use. Valid values are: */ +/* MEM_DOS, MEM_ANSI, MEM_NAME, MEM_NOBS. See the JPEG docs for details on */ +/* what each does */ +#define JMEMSYS MEM_ANSI + +#endif /* VMS */ + +/* + * CPU: HP PA-RISC + * OS: ConvexOS + */ +#if defined(CONVEX) || defined(CONVEXNATIVE) || defined(__convexc__) + +#ifndef CONVEX +#define CONVEX +#endif + +#ifdef GOT_MACHINE +If you get an error on this line more than one machine type has been defined. +Please check your Makefile. +#endif +#define GOT_MACHINE + +/* Extra include files required for this platform */ +#include <sys/types.h> +#include <sys/stat.h> +/* Set machine byte-format */ +#ifdef CONVEXNATIVE +/* For Convex machines with native format floats */ +#define DF_MT DFMT_CONVEXNATIVE +#else +#define DF_MT DFMT_CONVEX +#endif + +/* Define portable variable types */ +typedef void VOID; +typedef void *VOIDP; +typedef char char8; +typedef unsigned char uchar8; +typedef char int8; +typedef unsigned char uint8; +typedef short int int16; +typedef unsigned short int uint16; +typedef long int int32; +typedef unsigned long int uint32; +typedef int intn; +typedef unsigned int uintn; +typedef float float32; +typedef double float64; +typedef char *_fcd; /* Fortran character descriptor type */ +typedef int intf; /* size of INTEGERs in Fortran compiler */ + +/* Fortran compatibility macros */ +#define _fcdtocp(desc) (desc) /* Macro to convert from Fortran character descriptor to C 'char *' */ + +/* Choose the I/O package to use when interacting with the file */ +#ifdef HAVE_FMPOOL +#define FILELIB PAGEBUFIO /* enable page buffering */ +#else +#define FILELIB POSIXBUFIO +#endif + +/* JPEG #define's - Look in the JPEG docs before changing - (Q) */ + +/* Determine the memory manager we are going to use. Valid values are: */ +/* MEM_DOS, MEM_ANSI, MEM_NAME, MEM_NOBS. See the JPEG docs for details on */ +/* what each does */ +#define JMEMSYS MEM_ANSI +#define RIGHT_SHIFT_IS_UNSIGNED +#define INCLUDES_ARE_ANSI +#define HAVE_STDC + +#endif /* CONVEX */ + + +/* + * CPU: MIPS + * OS: Ultrix + */ +#if defined(MIPSEL) || ((defined(mips) || defined(__mips)) && (defined(ultrix) || defined(__ultrix))) + +#ifndef MIPSEL +#define MIPSEL +#endif + +#ifdef GOT_MACHINE +If you get an error on this line more than one machine type has been defined. +Please check your Makefile. +#endif +#define GOT_MACHINE 1 + +#ifndef __GNUC__ +#define DUMBCC /* because it is. for later use in macros -QAK */ +#endif /* __GNUC__ */ + +/* Extra include files required for this platform */ +#include <sys/types.h> +#include <sys/file.h> /* for unbuffered i/o stuff */ +#include <sys/stat.h> + +/* Set machine byte-format */ +#define DF_MT DFMT_MIPSEL + +/* Define portable variable types */ +typedef void VOID; +typedef void *VOIDP; +typedef char char8; +typedef unsigned char uchar8; +typedef char int8; +typedef unsigned char uint8; +typedef short int16; +typedef unsigned short uint16; +typedef int int32; +typedef unsigned int uint32; +typedef int intn; +typedef unsigned int uintn; +typedef float float32; +typedef double float64; +typedef char *_fcd; /* Fortran character descriptor type */ +typedef int intf; /* size of INTEGERs in Fortran compiler */ + +/* Fortran compatibility macros */ +#define FNAME_POST_UNDERSCORE /* Fortran function names require trailing underscore */ +#define _fcdtocp(desc) (desc) /* Macro to convert from Fortran character descriptor to C 'char *' */ + +/* Choose the I/O package to use when interacting with the file */ +#ifdef HAVE_FMPOOL +#define FILELIB PAGEBUFIO /* enable page buffering */ +#else +#define FILELIB POSIXBUFIO +#endif + +/* JPEG #define's - Look in the JPEG docs before changing - (Q) */ + +/* Determine the memory manager we are going to use. Valid values are: */ +/* MEM_DOS, MEM_ANSI, MEM_NAME, MEM_NOBS. See the JPEG docs for details on */ +/* what each does */ +#define JMEMSYS MEM_ANSI + +#endif /* MIPSEL */ + +/* + * CPU: Motorola 68K + * OS: NeXTSTEP + */ +#if defined(NEXT) || defined(NeXT) + +#ifndef NEXT +#define NEXT +#endif + +#ifdef GOT_MACHINE +If you get an error on this line more than one machine type has been defined. +Please check your Makefile. +#endif +#define GOT_MACHINE + +/* Extra include files required for this platform */ +#define isascii(c) (isprint(c) || iscntrl(c)) +#ifndef __GNUC__ +#include <memory.h> +#endif /* __GNUC__ */ +#include <sys/file.h> /* for unbuffered i/o stuff */ +#include <sys/stat.h> + +/* Set machine byte-format */ +#define DF_MT DFMT_NEXT + +/* Define portable variable types */ +typedef void VOID; +typedef void *VOIDP; +typedef char char8; +typedef unsigned char uchar8; +typedef char int8; +typedef unsigned char uint8; +typedef short int int16; +typedef unsigned short int uint16; +typedef long int int32; +typedef unsigned long int uint32; +typedef int intn; +typedef unsigned int uintn; +typedef float float32; +typedef double float64; +typedef char *_fcd; /* Fortran character descriptor type */ +typedef int intf; /* size of INTEGERs in Fortran compiler */ + +/* Fortran compatibility macros */ +#define FNAME_POST_UNDERSCORE /* Fortran function names require trailing underscore */ +#define _fcdtocp(desc) (desc) /* Macro to convert from Fortran character descriptor to C 'char *' */ + +/* Choose the I/O package to use when interacting with the file */ +#ifdef HAVE_FMPOOL +#define FILELIB PAGEBUFIO /* enable page buffering */ +#else +#define FILELIB POSIXBUFIO +#endif + +/* JPEG #define's - Look in the JPEG docs before changing - (Q) */ + +/* Determine the memory manager we are going to use. Valid values are: */ +/* MEM_DOS, MEM_ANSI, MEM_NAME, MEM_NOBS. See the JPEG docs for details on */ +/* what each does */ +#define JMEMSYS MEM_ANSI +#define HAVE_STDC +#define INCLUDES_ARE_ANSI + +#endif /* NEXT */ + +/* + * CPU: Motorola 88K (obscure CISC chip) + * OS: ? + */ +#if defined(MOTOROLA) || defined(m88k) + +#ifdef GOT_MACHINE +If you get an error on this line more than one machine type has been defined. +Please check your Makefile. +#endif +#define GOT_MACHINE + +/* Extra include files required for this platform */ +#ifndef __GNUC__ +#include <memory.h> +#endif /* __GNUC__ */ +#include <unistd.h> +#include <sys/file.h> /* for unbuffered i/o stuff */ +#include <sys/stat.h> +#ifndef O_RDONLY +#include <fcntl.h> /* for unbuffered i/o stuff */ +#endif /*O_RDONLY*/ + +/* Set machine byte-format */ +#define DF_MT DFMT_MOTOROLA + +/* Define portable variable types */ +typedef void VOID; +typedef void *VOIDP; +typedef char char8; +typedef unsigned char uchar8; +typedef char int8; +typedef unsigned char uint8; +typedef short int int16; +typedef unsigned short int uint16; +typedef long int int32; +typedef unsigned long int uint32; +typedef int intn; +typedef unsigned int uintn; +typedef float float32; +typedef double float64; +typedef char *_fcd; /* Fortran character descriptor type */ +typedef int intf; /* size of INTEGERs in Fortran compiler */ + +/* Fortran compatibility macros */ +#define FNAME_POST_UNDERSCORE /* Fortran function names require trailing underscore */ +#define _fcdtocp(desc) (desc) /* Macro to convert from Fortran character descriptor to C 'char *' */ + +/* Choose the I/O package to use when interacting with the file */ +#define FILELIB POSIXBUFIO + +/* JPEG #define's - Look in the JPEG docs before changing - (Q) */ + +/* Determine the memory manager we are going to use. Valid values are: */ +/* MEM_DOS, MEM_ANSI, MEM_NAME, MEM_NOBS. See the JPEG docs for details on */ +/* what each does */ +#define JMEMSYS MEM_ANSI + +#endif /* MOTOROLA */ + + +/* + * CPU: ? (Fujitsu VP series) + * OS: ? (UNIX) + */ +#if defined VP | defined __uxpm__ + +#ifndef VP +#define VP +#endif + +#ifdef GOT_MACHINE +If you get an error on this line more than one machine type has been defined. +Please check your Makefile. +#endif +#define GOT_MACHINE 1 + +/* Extra include files required for this platform */ +#include <memory.h> +#include <sys/types.h> +#include <sys/stat.h> + +/* Set machine byte-format */ +#define DF_MT DFMT_VP + +/* Define portable variable types */ +typedef void VOID; +typedef void *VOIDP; +typedef char char8; +typedef unsigned char uchar8; +typedef char int8; +typedef unsigned char uint8; +typedef short int int16; +typedef unsigned short int uint16; +typedef long int int32; +typedef unsigned long int uint32; +typedef int intn; +typedef unsigned int uintn; +typedef float float32; +typedef double float64; +typedef char *_fcd; /* Fortran character descriptor type */ +typedef int intf; /* size of INTEGERs in Fortran compiler */ + +/* Fortran compatibility macros */ +#define FNAME_POST_UNDERSCORE /* Fortran function names require trailing underscore */ +#define _fcdtocp(desc) (desc) /* Macro to convert from Fortran character descriptor to C 'char *' */ + +/* Choose the I/O package to use when interacting with the file */ +#define FILELIB POSIXBUFIO + +/* JPEG #define's - Look in the JPEG docs before changing - (Q) */ + +/* Determine the memory manager we are going to use. Valid values are: */ +/* MEM_DOS, MEM_ANSI, MEM_NAME, MEM_NOBS. See the JPEG docs for details on */ +/* what each does */ +#define JMEMSYS MEM_ANSI + +#endif /* VP */ + +/* + * CPU: Intel I860 (in Paragon system) + * OS: ? (UNIX) + */ +#if defined I860 | defined i860 + +#ifndef I860 +#define I860 +#endif + +#ifdef GOT_MACHINE +If you get an error on this line more than one machine type has been defined. +Please check your Makefile. +#endif +#define GOT_MACHINE 1 + +/* Extra include files required for this platform */ +#include <sys/types.h> +#include <sys/file.h> /* for unbuffered i/o stuff */ +#include <sys/stat.h> +#include <unistd.h> /* mis-using def. for SEEK_SET, but oh well */ + +/* Set machine byte-format */ +#define DF_MT DFMT_I860 + +/* Define portable variable types */ +typedef void VOID; +typedef void *VOIDP; +typedef char char8; +typedef unsigned char uchar8; +typedef char int8; +typedef unsigned char uint8; +typedef short int16; +typedef unsigned short uint16; +typedef int int32; +typedef unsigned int uint32; +typedef int intn; +typedef unsigned int uintn; +typedef float float32; +typedef double float64; +typedef char *_fcd; /* Fortran character descriptor type */ +typedef int intf; /* size of INTEGERs in Fortran compiler */ + +/* Fortran compatibility macros */ +#define FNAME_POST_UNDERSCORE /* Fortran function names require trailing underscore */ +#define _fcdtocp(desc) (desc) /* Macro to convert from Fortran character descriptor to C 'char *' */ + +/* Choose the I/O package to use when interacting with the file */ +#define FILELIB POSIXBUFIO + +/* JPEG #define's - Look in the JPEG docs before changing - (Q) */ + +/* Determine the memory manager we are going to use. Valid values are: */ +/* MEM_DOS, MEM_ANSI, MEM_NAME, MEM_NOBS. See the JPEG docs for details on */ +/* what each does */ +#define JMEMSYS MEM_ANSI + +#endif /* I860 */ + +#endif /* H5OPLAT_H */ + diff --git a/src/hdf5.h b/src/hdf5.h new file mode 100644 index 0000000..6f3c9bc --- /dev/null +++ b/src/hdf5.h @@ -0,0 +1,60 @@ +/**************************************************************************** + * NCSA HDF * + * Software Development Group * + * National Center for Supercomputing Applications * + * University of Illinois at Urbana-Champaign * + * 605 E. Springfield, Champaign IL 61820 * + * * + * For conditions of distribution and use, see the accompanying * + * hdf/COPYING file. * + * * + ****************************************************************************/ + +/* $Id$ */ + +/* + * This is the main HDF5 include file. Put further information in a particular + * header file and include that here, don't fill this file with lots of gunk... + */ + +#ifndef HDF5_H +#define HDF5_H + +/* Standard header files needed all the time */ +#include <stdio.h> +#include <stdlib.h> +#include <limits.h> +#include <string.h> + +/* PABLO support files */ +#ifdef HAVE_PABLO +#define IOTRACE +#include "IOTrace.h" +#include "ProcIDs.h" +#endif /* HAVE_PABLO */ + +/* Determine the system and set up basic info. */ +#include "hdf5plat.h" /* Platform/OS/CPU detection header file (should be first header included) */ + +/* Generic Data-Structure/Algorithm include files */ +#include "H5Aproto.h" /* Atom management routines */ + +/* Major HDF5 Include files */ +#include "hdf5meta.h" /* File Meta-data conversion macros, etc. */ +#include "hdf5fort.h" /* Fortran macros, etc. */ +#include "hdf5port.h" /* Portability macros for easier development */ +#include "hdf5gen.h" /* General global macros */ +#include "hdf5type.h" /* General global typedefs (uses basic types defined in hdf5plat.h) */ +#include "hdf5lims.h" /* Various global limits & version numbers on things */ +#include "H5Fproto.h" /* File access information and macros */ +#include "hdf5pabl.h" /* Pablo porting macros */ +#include "H5Eproto.h" /* Error reporting information */ +#include "H5Cproto.h" /* Template information */ +#include "H5Mproto.h" /* Meta-Object information */ +#include "H5Tproto.h" /* Datatype information */ +#include "H5Pproto.h" /* Dataspace information */ +#include "H5proto.h" /* Generic Interface information */ +#include "hdf5glob.h" /* Global & thread-specific variables */ + +#endif /* HDF5_H */ + diff --git a/src/hdf5fort.h b/src/hdf5fort.h new file mode 100644 index 0000000..21e9ffc --- /dev/null +++ b/src/hdf5fort.h @@ -0,0 +1,75 @@ +/**************************************************************************** + * NCSA HDF * + * Software Development Group * + * National Center for Supercomputing Applications * + * University of Illinois at Urbana-Champaign * + * 605 E. Springfield, Champaign IL 61820 * + * * + * For conditions of distribution and use, see the accompanying * + * hdf/COPYING file. * + * * + ****************************************************************************/ + +/* $Id$ */ + +/* + * This file contains Fortran compatibility/interface macros, etc. + */ + +#ifndef HDF5FORT_H +#define HDF5FORT_H + +/*---------------------------------------------------------------- +** MACRO FCALLKEYW for any special fortran-C stub keyword +** +** MacIntosh MPW LS-fortran needs pascal since it can interface +** best with pascal functions. +** Microsoft C and Fortran need __fortran for Fortran callable C +** routines. +** +** MACRO FRETVAL for any return value from a fortran-C stub function +** Replaces the older FCALLKEYW macro. +**---------------------------------------------------------------*/ +#ifdef FRETVAL +#undef FRETVAL +#endif + +#if defined(MAC) /* with LS FORTRAN */ +#ifndef ABSOFT +# define FCALLKEYW pascal +# define FRETVAL(x) pascal x +#endif /* ABSOFT */ +#endif + +#ifndef FRETVAL /* !MAC */ +# define FCALLKEYW /*NONE*/ +# define FRETVAL(x) x +#endif + + +/*---------------------------------------------------------------- +** MACRO FNAME for any fortran callable routine name. +** +** This macro prepends, appends, or does not modify a name +** passed as a macro parameter to it based on the FNAME_PRE_UNDERSCORE, +** FNAME_POST_UNDERSCORE macros set for a specific system. +** +**---------------------------------------------------------------*/ +#if defined(FNAME_PRE_UNDERSCORE) && defined(FNAME_POST_UNDERSCORE) +# define FNAME(x) _##x##_ +#endif +#if defined(FNAME_PRE_UNDERSCORE) && !defined(FNAME_POST_UNDERSCORE) +# define FNAME(x) _##x +#endif +#if !defined(FNAME_PRE_UNDERSCORE) && defined(FNAME_POST_UNDERSCORE) +# define FNAME(x) x##_ +#endif +#if !defined(FNAME_PRE_UNDERSCORE) && !defined(FNAME_POST_UNDERSCORE) +# define FNAME(x) x +#endif + + +#endif /* HDF5FORT_H */ + + + diff --git a/src/hdf5gen.h b/src/hdf5gen.h new file mode 100644 index 0000000..4d01685 --- /dev/null +++ b/src/hdf5gen.h @@ -0,0 +1,49 @@ +/**************************************************************************** + * NCSA HDF * + * Software Development Group * + * National Center for Supercomputing Applications * + * University of Illinois at Urbana-Champaign * + * 605 E. Springfield, Champaign IL 61820 * + * * + * For conditions of distribution and use, see the accompanying * + * hdf/COPYING file. * + * * + ****************************************************************************/ + +/* $Id$ */ + +/* + * This file contains general macros used throughout HDF5 library & interfaces + */ + +#ifndef HDF5GEN_H +#define HDF5GEN_H + +/* return code - since some unix/c routines use 0 and -1 as their return + code, and some assumption had been made in the code about that, it is + important to keep these constants the same values. For explicitly + boolean functions, use TRUE and FALSE */ + +#define SUCCEED 0 +#define FAIL (-1) + +/* boolean values, reminder: NEVER compare with numeric values */ + +#ifndef FALSE +# define FALSE 0 +#endif +#ifndef TRUE +# define TRUE (!FALSE) +#endif + +/* Function entry & exit macros */ +#define FUNC_ENTER(pablo_mask,pablo_func_id,interface_init_func,err) \ + { PABLO_TRACE_ON(pablo_mask,pablo_func_id); \ + if(library_initialize==FALSE) if(H5_init_library()==FAIL) HGOTO_ERROR(H5E_FUNC,H5E_CANTINIT,err); \ + if(thread_initialize==FALSE) if(H5_init_thread()==FAIL) HGOTO_ERROR(H5E_FUNC,H5E_CANTINIT,err); \ + if(interface_initialize==FALSE) if(interface_init_func()==FAIL) HGOTO_ERROR(H5E_FUNC,H5E_CANTINIT,err); } +#define FUNC_LEAVE(pablo_mask,pablo_func_id,return_value) \ + { PABLO_TRACE_OFF(pablo_mask,pablo_func_id); return(return_value); } + +#endif /* HDF5GEN_H */ + diff --git a/src/hdf5glob.h b/src/hdf5glob.h new file mode 100644 index 0000000..2fc752d --- /dev/null +++ b/src/hdf5glob.h @@ -0,0 +1,58 @@ +/**************************************************************************** + * NCSA HDF * + * Software Development Group * + * National Center for Supercomputing Applications * + * University of Illinois at Urbana-Champaign * + * 605 E. Springfield, Champaign IL 61820 * + * * + * For conditions of distribution and use, see the accompanying * + * hdf/COPYING file. * + * * + ****************************************************************************/ + +/* $Id$ */ + +/* + * Header file for global & thread-specific data + */ + +#ifndef HDF5GLOB_H +#define HDF5GLOB_H + +/* Library global variables */ +/* There should only be a few of these, don't add more unless you have a d*mn good reason! */ + +#ifndef HDF5_MASTER +extern +#endif /* HDF5_MASTER */ +intn library_initialize /* Whether we've initialized library global information yet */ +#ifdef HDF5_MASTER += FALSE +#endif /* HDF5_MASTER */ +; +#ifndef HDF5_MASTER +extern +#endif /* HDF5_MASTER */ +intn install_atexit /* Whether to install the atexit routine */ +#ifdef HDF5_MASTER += TRUE +#endif /* HDF5_MASTER */ +; + +/* Thread-specific variables */ +#ifndef HDF5_MASTER +extern +#endif /* HDF5_MASTER */ +intn thread_initialize /* Whether we've initialized thread global information yet */ +#ifdef HDF5_MASTER += FALSE +#endif /* HDF5_MASTER */ +; + +#ifndef HDF5_MASTER +extern +#endif /* HDF5_MASTER */ +int32 thrderrid; /* Thread-specific "global" error-handler ID */ + +#endif /* HDF5GLOB_H */ + diff --git a/src/hdf5lims.h b/src/hdf5lims.h new file mode 100644 index 0000000..dc8648d --- /dev/null +++ b/src/hdf5lims.h @@ -0,0 +1,60 @@ +/**************************************************************************** + * NCSA HDF * + * Software Development Group * + * National Center for Supercomputing Applications * + * University of Illinois at Urbana-Champaign * + * 605 E. Springfield, Champaign IL 61820 * + * * + * For conditions of distribution and use, see the accompanying * + * hdf/COPYING file. * + * * + ****************************************************************************/ + +/* $Id$ */ + +/* + * This file contains all global hard coded limits for the library, interface + * particular limits are defined in the interface header file. + */ + +#ifndef HDF5LIMS_H +#define HDF5LIMS_H + +/* Size of an OID in bytes */ +#define HDF5_OID_SIZE 8 + +/* Version #'s of library code */ +#define HDF5_MAJOR_VERSION 0 /* For major interface changes */ +#define HDF5_MINOR_VERSION 0 /* For minor interface changes */ +#define HDF5_RELEASE_VERSION 0 /* For interface tweaks & bug-fixes */ +#define HDF5_PATCH_VERSION 0 /* For small groups of bug fixes */ + +/* Version #'s of the major components of the file format */ +#define HDF5_BOOTBLOCK_VERSION 0 /* Version of the boot block format */ +#define HDF5_SMALLOBJECT_VERSION 0 /* Version of the Small-Object Heap */ +#define HDF5_FREESPACE_VERSION 0 /* Version of the Free-Space Info */ +#define HDF5_OBJECTDIR_VERSION 0 /* Version of the Object Directory format */ +#define HDF5_SHAREDHEADER_VERSION 0 /* Version of the Shared-Header Info */ + +/* Define the HDF5 file signature */ +#define HDF5_FILE_SIGNATURE "\211HDF\r\n\032\n" +#define HDF5_FILE_SIGNATURE_LEN 8 + +/* Maximum length of function name to push onto error stack */ +#define MAX_FUNC_NAME_LEN 32 + +/* Default sizes of the hash-tables for various atom groups */ +#define HDF5_ERRSTACK_HASHSIZE 64 +#define HDF5_FILEID_HASHSIZE 64 +#define HDF5_TEMPID_HASHSIZE 64 +#define HDF5_DATATYPEID_HASHSIZE 64 +#define HDF5_DATASPACEID_HASHSIZE 64 + +/* Default file-creation template values */ +#define HDF5_USERBLOCK_DEFAULT 0 /* Default to 0-byte sized user blocks */ +#define HDF5_OFFSETSIZE_DEFAULT 4 /* Default to 4-byte offsets */ +#define HDF5_LENGTHSIZE_DEFAULT 4 /* Default to 4-byte lengths */ +#define HDF5_BTREEPAGE_DEFAULT 1024 /* Default to 1024-byte B-tree pages */ + +#endif /* HDF5LIMS_H */ + diff --git a/src/hdf5meta.h b/src/hdf5meta.h new file mode 100644 index 0000000..025b4e6 --- /dev/null +++ b/src/hdf5meta.h @@ -0,0 +1,145 @@ +/**************************************************************************** + * NCSA HDF * + * Software Development Group * + * National Center for Supercomputing Applications * + * University of Illinois at Urbana-Champaign * + * 605 E. Springfield, Champaign IL 61820 * + * * + * For conditions of distribution and use, see the accompanying * + * hdf/COPYING file. * + * * + ****************************************************************************/ + +/* $Id$ */ + +/* + * This file contains macros & information for file meta information + * (offsets, lengths, etc.) + */ + +#ifndef HDF5META_H +#define HDF5META_H + +/*-----------------------------------------------------*/ +/* Encode and decode macros for file meta-data */ +/* (Currently, all file meta-data is little-endian) */ +/*-----------------------------------------------------*/ + +/* For non-little-endian platforms, encode each byte by itself */ +#if ((DF_MT&0xFFF0)!=0x4440) +# define INT16ENCODE(p, i) \ +{ *(p) = (uint8)((uintn)(i) & 0xff); (p)++; *(p) = (uint8)(((uintn)(i) >> 8) & 0xff); (p)++; } + +# define UINT16ENCODE(p, i) \ +{ *(p) = (uint8)((i) & 0xff); (p)++; *(p) = (uint8)(((uintn)(i) >> 8) & 0xff); (p)++; } + +# define INT32ENCODE(p, i) \ +{ *(p) = (uint8)((uint32)(i) & 0xff); (p)++; \ + *(p) = (uint8)(((uint32)(i) >> 8) & 0xff); (p)++; \ + *(p) = (uint8)(((uint32)(i) >> 16) & 0xff); (p)++; \ + *(p) = (uint8)(((uint32)(i) >> 24) & 0xff); (p)++; } + +# define UINT32ENCODE(p, i) \ +{ *(p) = (uint8)((i) & 0xff); (p)++; \ + *(p) = (uint8)(((i) >> 8) & 0xff); (p)++; \ + *(p) = (uint8)(((i) >> 16) & 0xff); (p)++; \ + *(p) = (uint8)(((i) >> 24) & 0xff); (p)++; } +#ifdef HDF5_HAVE_NATIVE_INT64 +# define INT64ENCODE(p, i) \ +{ *(p) = (uint8)((uint64)(i) & 0xff); (p)++; \ + *(p) = (uint8)(((uint64)(i) >> 8) & 0xff); (p)++; \ + *(p) = (uint8)(((uint64)(i) >> 16) & 0xff); (p)++; \ + *(p) = (uint8)(((uint64)(i) >> 24) & 0xff); (p)++; \ + *(p) = (uint8)(((uint64)(i) >> 32) & 0xff); (p)++; \ + *(p) = (uint8)(((uint64)(i) >> 40) & 0xff); (p)++; \ + *(p) = (uint8)(((uint64)(i) >> 48) & 0xff); (p)++; \ + *(p) = (uint8)(((uint64)(i) >> 56) & 0xff); (p)++; } + +# define UINT64ENCODE(p, i) \ +{ *(p) = (uint8)((i) & 0xff); (p)++; \ + *(p) = (uint8)(((i) >> 8) & 0xff); (p)++; \ + *(p) = (uint8)(((i) >> 16) & 0xff); (p)++; \ + *(p) = (uint8)(((i) >> 24) & 0xff); (p)++; \ + *(p) = (uint8)(((i) >> 32) & 0xff); (p)++; \ + *(p) = (uint8)(((i) >> 40) & 0xff); (p)++; \ + *(p) = (uint8)(((i) >> 48) & 0xff); (p)++; \ + *(p) = (uint8)(((i) >> 56) & 0xff); (p)++; } +#else /* HDF5_HAVE_NATIVE_INT64 */ +#error "Define int64 on platforms which don't support it" +#endif /* HDF5_HAVE_NATIVE_INT64 */ + +# define INT16DECODE(p, i) \ +{ (i) = (int16)((*(p) & 0xff)); (p)++; \ + (i) |= (int16)((*(p) & 0xff) << 8); (p)++; } + +# define UINT16DECODE(p, i) \ +{ (i) = (uint16)(*(p) & 0xff); (p)++; \ + (i) |= (uint16)((*(p) & 0xff) << 8); (p)++; } + +# define INT32DECODE(p, i) \ +{ (i) = (*(p) & 0xff); (p)++; \ + (i) |= ((int32)(*(p) & 0xff) << 8); (p)++; \ + (i) |= ((int32)(*(p) & 0xff) << 16); (p)++; \ + (i) |= ((int32)(*(p) & 0xff) << 24); (p)++; } + +# define UINT32DECODE(p, i) \ +{ (i) = (uint32)(*(p) & 0xff); (p)++; \ + (i) |= ((uint32)(*(p) & 0xff) << 8); (p)++; \ + (i) |= ((uint32)(*(p) & 0xff) << 16); (p)++; \ + (i) |= ((uint32)(*(p) & 0xff) << 24); (p)++; } + +#ifdef HDF5_HAVE_NATIVE_INT64 +#define INT64DECODE(p, i) \ +{ (i) = (*(p) & 0xff); (p)++; \ + (i) |= ((int64)(*(p) & 0xff) << 8); (p)++; \ + (i) |= ((int64)(*(p) & 0xff) << 16); (p)++; \ + (i) |= ((int64)(*(p) & 0xff) << 24); (p)++; \ + (i) |= ((int64)(*(p) & 0xff) << 32); (p)++; \ + (i) |= ((int64)(*(p) & 0xff) << 40); (p)++; \ + (i) |= ((int64)(*(p) & 0xff) << 48); (p)++; \ + (i) |= ((int64)(*(p) & 0xff) << 56); (p)++; } + +# define UINT64DECODE(p, i) \ +{ (i) = (uint64)(*(p) & 0xff); (p)++; \ + (i) |= ((uint64)(*(p) & 0xff) << 8); (p)++; \ + (i) |= ((uint64)(*(p) & 0xff) << 16); (p)++; \ + (i) |= ((uint64)(*(p) & 0xff) << 24); (p)++; \ + (i) |= ((uint64)(*(p) & 0xff) << 32); (p)++; \ + (i) |= ((uint64)(*(p) & 0xff) << 40); (p)++; \ + (i) |= ((uint64)(*(p) & 0xff) << 48); (p)++; \ + (i) |= ((uint64)(*(p) & 0xff) << 56); (p)++; } +#else /* HDF5_HAVE_NATIVE_INT64 */ +#error "Define int64 on platforms which don't support it" +#endif /* HDF5_HAVE_NATIVE_INT64 */ +#else /* platform has little-endian integers */ +/* For little-endian platforms, make the compiler do the work */ +# define INT16ENCODE(p, i) { *((int16 *)(p)) = (int16)(i); (p)+=2; } +# define UINT16ENCODE(p, i) { *((uint16 *)(p)) = (uint16)(i); (p)+=2; } +# define INT32ENCODE(p, i) { *((int32 *)(p)) = (int32)(i); (p)+=4; } +# define UINT32ENCODE(p, i) { *((uint32 *)(p)) = (uint32)(i); (p)+=4; } +#ifdef HDF5_HAVE_NATIVE_INT64 +# define INT64ENCODE(p, i) { *((int64 *)(p)) = (int64)(i); (p)+=8; } +# define UINT64ENCODE(p, i) { *((uint64 *)(p)) = (uint64)(i); (p)+=8; } +#else /* HDF5_HAVE_NATIVE_INT64 */ +#error "Define int64 on platforms which don't support it" +#endif /* HDF5_HAVE_NATIVE_INT64 */ +# define INT16DECODE(p, i) { (i) = (int16)(*(int16 *)(p)); (p)+=2; } +# define UINT16DECODE(p, i) { (i) = (uint16)(*(uint16 *)(p)); (p)+=2; } +# define INT32DECODE(p, i) { (i) = (int32)(*(int32 *)(p)); (p)+=4; } +# define UINT32DECODE(p, i) { (i) = (uint32)(*(uint32 *)(p)); (p)+=4; } +#ifdef HDF5_HAVE_NATIVE_INT64 +# define INT64DECODE(p, i) { (i) = (int64)(*(int64 *)(p)); (p)+=8; } +# define UINT64DECODE(p, i) { (i) = (uint64)(*(uint64 *)(p)); (p)+=8; } +#else /* HDF5_HAVE_NATIVE_INT64 */ +#error "Define int64 on platforms which don't support it" +#endif /* HDF5_HAVE_NATIVE_INT64 */ +#endif + +# define NBYTEENCODE(d, s, n) { HDmemcpy(d,s,n); p+=n } + +/* Note! the NBYTEDECODE macro is backwards from the memcpy() routine, */ +/* in the spirit of the other DECODE macros */ +# define NBYTEDECODE(s, d, n) { HDmemcpy(d,s,n); p+=n } + +#endif /* HDF5I_H */ + diff --git a/src/hdf5pabl.h b/src/hdf5pabl.h new file mode 100644 index 0000000..0df5913 --- /dev/null +++ b/src/hdf5pabl.h @@ -0,0 +1,32 @@ +/**************************************************************************** + * NCSA HDF * + * Software Development Group * + * National Center for Supercomputing Applications * + * University of Illinois at Urbana-Champaign * + * 605 E. Springfield, Champaign IL 61820 * + * * + * For conditions of distribution and use, see the accompanying * + * hdf/COPYING file. * + * * + ****************************************************************************/ + +/* $Id$ */ + +/* + * Header file for Pablo compatibility + */ + +#ifndef HDF5PABL_H +#define HDF5PABL_H + +#ifdef HAVE_PABLO +#define PABLO_TRACE_ON(m, f) TRACE_ON(m,f) +#define PABLO_TRACE_OFF(m, f) TRACE_OFF(m,f) +#else /* no Pablo tracing enabled */ +#define PABLO_TRACE_ON(m, f) +#define PABLO_TRACE_OFF(m, f) +#endif /* HAVE_PABLO */ + +#endif /* HDF5PABL_H */ + + diff --git a/src/hdf5plat.h b/src/hdf5plat.h new file mode 100644 index 0000000..5c5f649 --- /dev/null +++ b/src/hdf5plat.h @@ -0,0 +1,750 @@ +/**************************************************************************** + * NCSA HDF * + * Software Development Group * + * National Center for Supercomputing Applications * + * University of Illinois at Urbana-Champaign * + * 605 E. Springfield, Champaign IL 61820 * + * * + * For conditions of distribution and use, see the accompanying * + * hdf/COPYING file. * + * * + ****************************************************************************/ + +/* $Id$ */ + +/* + * This file contains platform/CPU/OS detection macros, etc. + */ + +#ifndef HDF5PLAT_H +#define HDF5PLAT_H + +/*--------------------------------------------------------------------------*/ +/* MT/NT constants */ +/* Six MT nibbles represent float64, float32, int64, int32, int16, and */ +/* int8 (from most significant to least significant). The unsigned */ +/* form of each type is assumed to be in the same format as the signed */ +/* type. The top two nibbles (8-bits) are currently unused. */ +/* The values for each nibble are: */ +/* 1 - Big Endian */ +/* 2 - VAX */ +/* 3 - Cray */ +/* 4 - Little Endian */ +/* 5 - Convex */ +/* 6 - Fujitsu VP */ +/*--------------------------------------------------------------------------*/ +#define DFMT_SUN 0x00111111 +#define DFMT_ALLIANT 0x00111111 +#define DFMT_IRIX 0x00111111 +#define DFMT_APOLLO 0x00111111 +#define DFMT_IBM6000 0x00111111 +#define DFMT_HP9000 0x00111111 +#define DFMT_CONVEXNATIVE 0x00551111 +#define DFMT_CONVEX 0x00111111 +#define DFMT_UNICOS 0x00333331 +#define DFMT_CTSS 0x00333331 +#define DFMT_VAX 0x00222221 +#define DFMT_MIPSEL 0x00444441 +#define DFMT_PC 0x00444441 +#define DFMT_MAC 0x00111111 +#define DFMT_SUN386 0x00444441 +#define DFMT_NEXT 0x00111111 +#define DFMT_MOTOROLA 0x00111111 +#define DFMT_ALPHA 0x00444441 +#define DFMT_VP 0x00661111 +#define DFMT_I860 0x00444441 +#define DFMT_CRAYMPP 0x00117771 + +/* I/O library constants */ +#define POSIXUNBUFIO 1 /* POSIX-compliant un-buffered I/O */ +#define POSIXBUFIO 2 /* POSIX buffered I/O */ +#define MACIO 3 /* Macintosh I/O */ +#define WINNTIO 4 /* 32-bit Windows File I/O */ +#define PAGEBUFIO 5 /* page buffering - fmpool */ + +#ifdef GOT_MACHINE +#undef GOT_MACHINE +#endif + +/*------------------------------------------------------------------------- + * Define options for each platform + *-------------------------------------------------------------------------*/ + +#if (defined(SUN) || defined(sun) || defined(__sun__) || defined(__SUNPRO_C)) & !defined(__i386) +#ifdef __STDC__ +#define ANSISUN +#else /* __STDC__ */ +#define KNRSUN +#endif /* __STDC__ */ +#endif /* SUN || sun */ + +/* + * CPU: Sparc + * OS: Solaris 1.x, SunOS 4.1.x + */ +#if defined(ANSISUN) + +#if !defined(SUN) +#define SUN +#endif + +#ifdef GOT_MACHINE +If you get an error on this line more than one machine type has been defined. +Please check your Makefile. +#endif +#define GOT_MACHINE + +/* Extra include files required for this platform */ +#include <unistd.h> /* for some file I/O stuff */ +#include <sys/time.h> +#include <sys/file.h> /* for unbuffered i/o stuff */ +#include <sys/stat.h> + +/* Set machine byte-format */ +#define DF_MT DFMT_SUN + +/* Define portable variable types */ +typedef void VOID; +typedef void *VOIDP; +typedef char char8; +typedef unsigned char uchar8; +typedef char int8; +typedef unsigned char uint8; +typedef short int int16; +typedef unsigned short int uint16; +typedef long int int32; +typedef unsigned long int uint32; +typedef int intn; +typedef unsigned int uintn; +typedef float float32; +typedef double float64; +typedef char *_fcd; /* Fortran character descriptor type */ +typedef int intf; /* size of INTEGERs in Fortran compiler */ + +/* Fortran compatibility macros */ +#define FNAME_POST_UNDERSCORE /* Fortran function names require trailing underscore */ +#define _fcdtocp(desc) (desc) /* Macro to convert from Fortran character descriptor to C 'char *' */ + +/* Choose the I/O package to use when interacting with the file */ +#ifdef HAVE_FMPOOL +#define FILELIB PAGEBUFIO /* enable page buffering */ +#else +#define FILELIB POSIXBUFIO +#endif + +/* JPEG #define's - Look in the JPEG docs before changing - (Q) */ + +/* Determine the memory manager we are going to use. Valid values are: */ +/* MEM_DOS, MEM_ANSI, MEM_NAME, MEM_NOBS. See the JPEG docs for details on */ +/* what each does */ +#define JMEMSYS MEM_ANSI +#define HAVE_STDC +#define INCLUDES_ARE_ANSI + +#endif /* ANSISUN */ + +/* + * CPU: IBM RS/6000 chip/PowerPC + * OS: AIX + */ +#if defined(IBM6000) || defined(_AIX) + +#ifndef IBM6000 +#define IBM6000 +#endif + +#ifdef GOT_MACHINE +If you get an error on this line more than one machine type has been defined. +Please check your Makefile. +#endif +#define GOT_MACHINE + +/* Extra include files required for this platform */ +# define BSD +#ifndef __GNUC__ +#include <memory.h> +#endif /* __GNUC__ */ +#include <sys/file.h> /* for unbuffered i/o stuff */ +#include <sys/stat.h> + +/* Set machine byte-format */ +#define DF_MT DFMT_IBM6000 + +/* Define portable variable types */ +typedef void VOID; +typedef void *VOIDP; +typedef char *_fcd; /* Fortran character descriptor type */ +typedef char char8; +typedef unsigned char uchar8; +typedef char int8; +typedef unsigned char uint8; +typedef short int int16; +typedef unsigned short int uint16; +typedef long int int32; +typedef unsigned long int uint32; +typedef int intn; +typedef unsigned int uintn; +typedef float float32; +typedef double float64; +typedef int intf; /* size of INTEGERs in Fortran compiler */ + +/* Fortran compatibility macros */ +#define _fcdtocp(desc) (desc) /* Macro to convert from Fortran character descriptor to C 'char *' */ + +/* Choose the I/O package to use when interacting with the file */ +#ifdef HAVE_FMPOOL +#define FILELIB PAGEBUFIO /* enable page buffering */ +#else +#define FILELIB POSIXBUFIO +#endif + +/* JPEG #define's - Look in the JPEG docs before changing - (Q) */ + +/* Determine the memory manager we are going to use. Valid values are: */ +/* MEM_DOS, MEM_ANSI, MEM_NAME, MEM_NOBS. See the JPEG docs for details on */ +/* what each does */ +#define JMEMSYS MEM_ANSI +#define HAVE_STDC +#define INCLUDES_ARE_ANSI + +#endif /* IBM6000 */ + +/* + * CPU: HP PA-RISC + * OS: HP/UX (ConvexOS?) + */ +#if defined(HP9000) || (!defined(__convexc__) && (defined(hpux) || defined(__hpux))) + +#ifndef HP9000 +#define HP9000 +#endif + +#ifdef GOT_MACHINE +If you get an error on this line more than one machine type has been defined. +Please check your Makefile. +#endif +#define GOT_MACHINE + +/* Extra include files required for this platform */ +#define HAVE_UNISTD_H /* unistd.h - close, fork,..etc */ +# define BSD +#ifndef __GNUC__ +#include <memory.h> +#endif /* __GNUC__ */ +#include <sys/file.h> /* for unbuffered i/o stuff */ +#include <sys/stat.h> + +/* Set machine byte-format */ +#define DF_MT DFMT_HP9000 + +/* Define portable variable types */ +typedef void VOID; +typedef void *VOIDP; +typedef char *_fcd; /* Fortran character descriptor type */ +typedef char char8; +typedef unsigned char uchar8; +typedef char int8; +typedef unsigned char uint8; +typedef short int int16; +typedef unsigned short int uint16; +typedef long int int32; +typedef unsigned long int uint32; +typedef int intn; +typedef unsigned int uintn; +typedef float float32; +typedef double float64; +typedef int intf; /* size of INTEGERs in Fortran compiler */ + +/* Fortran compatibility macros */ +#define _fcdtocp(desc) (desc) /* Macro to convert from Fortran character descriptor to C 'char *' */ + +/* Choose the I/O package to use when interacting with the file */ +#ifdef HAVE_FMPOOL +#define FILELIB PAGEBUFIO /* enable page buffering */ +#else +#define FILELIB POSIXBUFIO +#endif + +/* JPEG #define's - Look in the JPEG docs before changing - (Q) */ + +/* Determine the memory manager we are going to use. Valid values are: */ +/* MEM_DOS, MEM_ANSI, MEM_NAME, MEM_NOBS. See the JPEG docs for details on */ +/* what each does */ +#define JMEMSYS MEM_ANSI + +#endif /* HP9000 */ + + +/* + * CPU: MIPS + * OS: IRIX + */ +#if defined(IRIX) || defined(IRIS4) || defined(sgi) || defined(__sgi__) || defined(__sgi) + +#ifndef IRIX +#define IRIX +#endif + +#ifdef GOT_MACHINE +If you get an error on this line more than one machine type has been defined. +Please check your Makefile. +#endif +#define GOT_MACHINE 1 + +/* Extra include files required for this platform */ +# define BSD +#ifndef __GNUC__ +#include <memory.h> +#endif /* __GNUC__ */ +#include <sys/file.h> /* for unbuffered i/o stuff */ +#include <sys/stat.h> + +/* Set machine byte-format */ +#define DF_MT DFMT_IRIX + +/* Define portable variable types */ +typedef void VOID; +typedef void *VOIDP; +typedef char *_fcd; /* Fortran character descriptor type */ +typedef signed char char8; +typedef unsigned char uchar8; +typedef signed char int8; +typedef unsigned char uint8; +typedef short int int16; +typedef unsigned short int uint16; +typedef int int32; +typedef unsigned int uint32; +typedef int intn; +typedef unsigned int uintn; +typedef float float32; +typedef double float64; +typedef int intf; /* size of INTEGERs in Fortran compiler */ + +/* Fortran compatibility macros */ +#define FNAME_POST_UNDERSCORE /* Fortran function names require trailing underscore */ +#define _fcdtocp(desc) (desc) /* Macro to convert from Fortran character descriptor to C 'char *' */ + +/* Choose the I/O package to use when interacting with the file */ +#ifdef HAVE_FMPOOL +#define FILELIB PAGEBUFIO /* enable page buffering */ +#else +#define FILELIB POSIXBUFIO +#endif + +/* JPEG #define's - Look in the JPEG docs before changing - (Q) */ + +/* Determine the memory manager we are going to use. Valid values are: */ +/* MEM_DOS, MEM_ANSI, MEM_NAME, MEM_NOBS. See the JPEG docs for details on */ +/* what each does */ +#define JMEMSYS MEM_ANSI +#define HAVE_STDC +#define INCLUDES_ARE_ANSI + +#endif /* IRIX */ + +/* + * CPU: Cray Vector CPU (is there a name for these? :-) + * OS: UNICOS + */ +#if (defined(UNICOS) || defined(_UNICOS)) && !defined(_CRAYMPP) + +#ifndef UNICOS +#define UNICOS +#endif + +#ifdef GOT_MACHINE +If you get an error on this line more than one machine type has been defined. +Please check your Makefile. +#endif +#define GOT_MACHINE 1 + +/* Extra include files required for this platform */ +#include <memory.h> +#include <fortran.h> +#ifndef O_RDONLY +#include <fcntl.h> /* for unbuffered i/o stuff */ +#define L_INCR 1 +#include <sys/stat.h> +#endif /*O_RDONLY*/ + +/* Set machine byte-format */ +#define DF_MT DFMT_UNICOS + +/* Define portable variable types */ +typedef void VOID; +typedef void *VOIDP; +#ifdef OLD_WAY /* May need to be included on other machines than the C-90 */ +typedef char *_fcd; /* Fortran character descriptor type */ +#endif /* OLD_WAY */ +typedef signed char char8; +typedef unsigned char uchar8; +typedef signed char int8; +typedef unsigned char uint8; +typedef int int16; +typedef unsigned int uint16; +typedef int int32; +typedef unsigned int uint32; +typedef int intn; +typedef unsigned int uintn; +typedef float float32; +typedef double float64; +typedef int intf; /* size of INTEGERs in Fortran compiler */ + +/* Fortran compatibility macros */ +#define DF_CAPFNAMES /* fortran names are in all caps */ +/* fcdtocp(desc) is defined in compiler header files */ + +/* Choose the I/O package to use when interacting with the file */ +#ifdef HAVE_FMPOOL +#define FILELIB PAGEBUFIO /* enable page buffering */ +#else +#define FILELIB POSIXBUFIO +#endif + +/* JPEG #define's - Look in the JPEG docs before changing - (Q) */ + +/* Determine the memory manager we are going to use. Valid values are: */ +/* MEM_DOS, MEM_ANSI, MEM_NAME, MEM_NOBS. See the JPEG docs for details on */ +/* what each does */ +#define JMEMSYS MEM_ANSI +#define RIGHT_SHIFT_IS_UNSIGNED +#define CHAR_IS_UNSIGNED + +#endif /* UNICOS */ + +/* + * CPU: Cray Vector CPU (is there a name for these? :-) + * OS: UNICOS (on massively parallel systems, like T3D & T3E) + */ +#if defined(_CRAYMPP) + +#ifndef CRAYMPP +#define CRAYMPP +#endif + +#ifdef GOT_MACHINE +If you get an error on this line more than one machine type has been defined. +Please check your Makefile. +#endif +#define GOT_MACHINE 1 + +/* Extra include files required for this platform */ +#include <memory.h> +#include <fortran.h> +#ifndef O_RDONLY +#include <fcntl.h> /* for unbuffered i/o stuff */ +#define L_INCR 1 +#include <sys/stat.h> +#endif /*O_RDONLY*/ + +/* Set machine byte-format */ +#define DF_MT DFMT_CRAYMPP + +/* Define portable variable types */ +typedef void VOID; +typedef void *VOIDP; +#ifdef OLD_WAY /* May need to be included on other machines than the C-90 */ +typedef char *_fcd; /* Fortran character descriptor type */ +#endif /* OLD_WAY */ +typedef signed char char8; +typedef unsigned char uchar8; +typedef signed char int8; +typedef unsigned char uint8; +typedef short int16; +typedef unsigned short uint16; +typedef short int32; +typedef unsigned short uint32; +typedef int intn; +typedef unsigned int uintn; +typedef float float32; +typedef double float64; +typedef int intf; /* size of INTEGERs in Fortran compiler */ + +/* Fortran compatibility macros */ +#define DF_CAPFNAMES /* fortran names are in all caps */ +/* fcdtocp(desc) is defined in compiler header files */ + +/* Choose the I/O package to use when interacting with the file */ +#ifdef HAVE_FMPOOL +#define FILELIB PAGEBUFIO /* enable page buffering */ +#else +#define FILELIB POSIXBUFIO +#endif + +/* JPEG #define's - Look in the JPEG docs before changing - (Q) */ + +/* Determine the memory manager we are going to use. Valid values are: */ +/* MEM_DOS, MEM_ANSI, MEM_NAME, MEM_NOBS. See the JPEG docs for details on */ +/* what each does */ +#define JMEMSYS MEM_ANSI +#define RIGHT_SHIFT_IS_UNSIGNED +#define CHAR_IS_UNSIGNED + +#endif /* CRAYMPP */ + + +/* + * CPU: Motorola 68K, PowerPC (both?) + * OS: MacOS + */ +#if defined(MAC) || defined(macintosh) || defined(__MWERKS__) || defined (SYMANTEC_C) + +#ifdef GOT_MACHINE +If you get an error on this line more than one machine type has been defined. +Please check your Makefile. +#endif +#define GOT_MACHINE 1 + +/* Extra include files required for this platform */ +#include <memory.h> /* malloc stuff for MPW */ +#include <fcntl.h> /* unbuffered I/O stuff for MPW */ +#ifdef __MWERKS__ /* Metrowerks */ +#include <sioux.h> +#include <console.h> +#endif +#ifdef SYMANTEC_C /* for SYMANTEC C */ +#include <unix.h> +#define isascii(c) (isprint(c) || iscntrl(c)) +#else /* MPW, possibly others */ +#include <Files.h> /* for unbuffered I/O stuff */ +#endif /* SYMANTEC_C*/ +#define DF_DYNAMIC /* use dynamic allocation */ + +/* Set machine byte-format */ +#define DF_MT DFMT_MAC + +/* Define portable variable types */ +typedef void VOID; +typedef void *VOIDP; +typedef char char8; +typedef unsigned char uchar8; +typedef char int8; +typedef unsigned char uint8; +typedef short int int16; +typedef unsigned short int uint16; +typedef long int int32; +typedef unsigned long int uint32; +typedef int intn; +typedef unsigned int uintn; +typedef float float32; +typedef double float64; +typedef char *_fcd; /* Fortran character descriptor type */ +typedef int intf; /* size of INTEGERs in Fortran compiler */ + +/* Fortran compatibility macros */ +#ifndef ABSOFT +#define DF_CAPFNAMES /* fortran names are in all caps */ +#endif /* ABSOFT */ +#define _fcdtocp(desc) (desc) /* Macro to convert from Fortran character descriptor to C 'char *' */ + +void exit(int status); + +/* Choose the I/O package to use when interacting with the file */ +#define FILELIB MACIO + +/* JPEG #define's - Look in the JPEG docs before changing - (Q) */ + +/* Determine the memory manager we are going to use. Valid values are: */ +/* MEM_DOS, MEM_ANSI, MEM_NAME, MEM_NOBS. See the JPEG docs for details on */ +/* what each does */ +#define JMEMSYS MEM_ANSI + +#endif /*MAC*/ + +/* + * CPU: Intel x86 + * OS: MS Windows '95, Windows NT (& Dos32?), also Linux & FreeBSD + */ +/* Metrowerks compilier defines some PC stuff so need to exclude this on the MAC */ +#if !(defined(__MWERKS__) || defined(MAC)) + +#if defined INTEL86 || defined M_I86 || defined M_I386 || defined DOS386 || defined __i386 || defined UNIX386 +#ifndef INTEL86 +#define INTEL86 +#endif /* INTEL86 */ + +#if !defined UNIX386 && (defined unix || defined __unix) +#define UNIX386 +#endif /* UNIX386 */ + +#if !defined DOS386 && defined M_I386 +#define DOS386 +#endif /* M_I386 && !DOS386 */ + +#if defined _WINDOWS || defined WIN32 +#define WIN386 +#endif /* _WINDOWS | WIN32 */ + +#if defined WIN386 || defined DOS386 || defined UNIX386 +#define INTEL386 +#endif /* WIN386 | DOS386 | UNIX386 */ + +#ifdef GOT_MACHINE +If you get an error on this line more than one machine type has been defined. +Please check your Makefile. +#endif +#define GOT_MACHINE 1 + +/* Extra include files required for this platform */ +#include <fcntl.h> +#ifdef UNIX386 +#include <sys/types.h> /* for unbuffered file I/O */ +#include <sys/stat.h> +#include <unistd.h> +#else /* !UNIX386 */ +#include <sys\types.h> /* for unbuffered file I/O */ +#include <sys\stat.h> +#include <io.h> +#include <conio.h> /* for debugging getch() calls */ +#include <malloc.h> +#endif /* UNIX386 */ +#include <ctype.h> /* for character macros */ +#ifdef __WATCOMC__ +#include <stddef.h> /* for the 'fortran' pragma */ +#endif +#if defined WIN386 +#ifndef GMEM_MOVEABLE /* check if windows header is already included */ +#include <windows.h> /* include the windows headers */ +#include <winnt.h> +#define HAVE_BOOLEAN +#endif /* GMEM_MOVEABLE */ +#endif /* WIN386 */ + +/* Set machine byte-format */ +#define DF_MT DFMT_PC + +/* Define portable variable types */ +#ifndef VOID /* The stupid windows.h header file uses a #define instead of a typedef */ +typedef void VOID; +#endif /* end VOID */ +typedef void * VOIDP; +typedef char char8; +typedef unsigned char uchar8; +typedef char int8; +typedef unsigned char uint8; +typedef short int int16; +typedef unsigned short int uint16; +typedef long int int32; +typedef unsigned long int uint32; +#ifdef __GNUC__ +#define HDF5_HAVE_NATIVE_INT64 +typedef long long int int64; /* 64-bit integers! */ +typedef unsigned long long int uint64; +#endif +typedef int intn; +typedef unsigned int uintn; +typedef float float32; +typedef double float64; +typedef char *_fcd; /* Fortran character descriptor type */ +typedef long intf; /* size of INTEGERs in Fortran compiler */ + +/* Fortran compatibility macros */ +#if defined UNIX386 +#define FNAME_POST_UNDERSCORE /* Fortran function names require trailing underscore */ +#elif defined INTEL386 +#define DF_CAPFNAMES /* Fortran function names need to be all-caps */ +#endif +#define _fcdtocp(desc) (desc) /* Macro to convert from Fortran character descriptor to C 'char *' */ + +/* Choose the I/O package to use when interacting with the file */ +#if defined WIN386 +#define FILELIB WINNTIO +#else +#ifdef HAVE_FMPOOL +#define FILELIB PAGEBUFIO /* enable page buffering */ +#else +#define FILELIB POSIXBUFIO +#endif +#endif /* WIN386 */ + +/* JPEG #define's - Look in the JPEG docs before changing - (Q) */ + +/* Determine the memory manager we are going to use. Valid values are: */ +/* MEM_DOS, MEM_ANSI, MEM_NAME, MEM_NOBS. See the JPEG docs for details on */ +/* what each does */ +#define JMEMSYS MEM_ANSI +#define HAVE_STDC +#define INCLUDES_ARE_ANSI + +#endif /* INTEL86 */ +#endif /* !(defined(__MWERKS__) || defined(MAC)) */ + + +/* + * CPU: Alpha + * OS: Dec Unix (used to be called OSF/1) + */ +#if defined DEC_ALPHA || (defined __alpha && defined __unix__) + +#ifndef DEC_ALPHA +#define DEC_ALPHA +#endif + +#ifdef GOT_MACHINE +If you get an error on this line more than one machine type has been defined. +Please check your Makefile. +#endif +#define GOT_MACHINE + +/* Extra include files required for this platform */ +#include <sys/file.h> /* for unbuffered i/o stuff */ +#include <sys/stat.h> + +/* Set machine byte-format */ +#define DF_MT DFMT_ALPHA + +/* Define portable variable types */ +typedef void VOID; +typedef void *VOIDP; +typedef char char8; +typedef unsigned char uchar8; +typedef char int8; +typedef unsigned char uint8; +typedef short int int16; +typedef unsigned short int uint16; +#ifndef __rpc_types_h +typedef int int32; +typedef unsigned int uint32; +#endif /* __rpc_types_h */ +typedef int intn; +typedef unsigned int uintn; +typedef float float32; +typedef double float64; +typedef char *_fcd; /* Fortran character descriptor type */ +typedef int intf; /* size of INTEGERs in Fortran compiler */ + +/* Fortran compatibility macros */ +#define FNAME_POST_UNDERSCORE /* Fortran function names require trailing underscore */ +#define _fcdtocp(desc) (desc) /* Macro to convert from Fortran character descriptor to C 'char *' */ + +/* Choose the I/O package to use when interacting with the file */ +#ifdef HAVE_FMPOOL +#define FILELIB PAGEBUFIO /* enable page buffering */ +#else +#define FILELIB POSIXBUFIO +#endif + +/* JPEG #define's - Look in the JPEG docs before changing - (Q) */ + +/* Determine the memory manager we are going to use. Valid values are: */ +/* MEM_DOS, MEM_ANSI, MEM_NAME, MEM_NOBS. See the JPEG docs for details on */ +/* what each does */ +#define JMEMSYS MEM_ANSI +#ifdef __GNUC__ +#define HAVE_STDC +#define INCLUDES_ARE_ANSI +#endif + +#endif /* DEC_ALPHA */ + +#include "h5oplat.h" /* include definitions for old, untested platforms */ + +/* Check if we've correctly determined the platform we are compiling in/for */ +#ifndef GOT_MACHINE +No machine type has been defined. Your Makefile needs to have someing like +-DSUN or -DUNICOS in order for the HDF internal structures to be defined +correctly. +#endif + +#endif /* HDF5PLAT_H */ + diff --git a/src/hdf5port.h b/src/hdf5port.h new file mode 100644 index 0000000..bdec34f --- /dev/null +++ b/src/hdf5port.h @@ -0,0 +1,202 @@ +/**************************************************************************** + * NCSA HDF * + * Software Development Group * + * National Center for Supercomputing Applications * + * University of Illinois at Urbana-Champaign * + * 605 E. Springfield, Champaign IL 61820 * + * * + * For conditions of distribution and use, see the accompanying * + * hdf/COPYING file. * + * * + ****************************************************************************/ + +/* $Id$ */ + +/* + * This file contains portability macros to ease moving the library between + * the various platforms. + */ + +#ifndef HDF5PORT_H +#define HDF5PORT_H + +/************************************************************************** +* Generally useful macro definitions +**************************************************************************/ +#ifndef MIN +#define MIN(a,b) (((a)<(b)) ? (a) : (b)) +#endif +#ifndef MAX +#define MAX(a,b) (((a)>(b)) ? (a) : (b)) +#endif + +/************************************************************************** +* Macros to work around ANSI C portability problems. +**************************************************************************/ +#ifdef DUMBCC +#define CONSTR(v,s) char *v=s +#else +#define CONSTR(v,s) static const char v[]=s +#endif + +/* -------------------------- File I/O Functions -------------------------- */ +/* FILELIB -- file library to use for file access: 1 stdio, 2 fcntl + default to stdio library i.e. POSIX buffered I/O */ + +#ifndef FILELIB +# define FILELIB POSIXBUFIO /* POSIX buffered I/O is the default */ +#endif /* FILELIB */ + +#if (FILELIB == POSIXBUFIO) +typedef FILE *hdf_file_t; +#ifdef VMS +/* For VMS, use "mbc=64" to improve performance */ +# define H5FI_OPEN(p, a) (((a)&H5ACC_WRITE) ? fopen((p),"r+","mbc=64") : fopen((p), "r", "mbc=64")) +# define H5FI_CREATE(p) (fopen((p), "w+", "mbc=64")) +#else /* !VMS */ +#if defined SUN && defined (__GNUC__) +# define H5FI_OPEN(p, a) (((a)&H5ACC_WRITE) ? fopen((p), "r+") : fopen((p), "r")) +# define H5FI_CREATE(p) (fopen((p), "w+")) +#else /* !SUN w/ GNU CC */ +# define H5FI_OPEN(p, a) (((a)&H5ACC_WRITE) ? fopen((p), "rb+") : fopen((p), "rb")) +# define H5FI_CREATE(p) (fopen((p), "wb+")) +#endif /* !SUN w/ GNU CC */ +#endif /* VMS */ +# define H5FI_READ(f, b, n) (((size_t)(n) == (size_t)fread((b), 1, (size_t)(n), (f))) ? SUCCEED : FAIL) +# define H5FI_WRITE(f, b, n) (((size_t)(n) == (size_t)fwrite((b), 1, (size_t)(n), (f))) ? SUCCEED : FAIL) +# define H5FI_CLOSE(f) (fclose(f)) +# define H5FI_FLUSH(f) (fflush(f)==0 ? SUCCEED : FAIL) +# define H5FI_SEEK(f,o) (fseek((f), (long)(o), SEEK_SET)==0 ? SUCCEED : FAIL) +# define H5FI_SEEK_CUR(f,o) (fseek((f), (long)(o), SEEK_CUR)==0 ? SUCCEED : FAIL) +# define H5FI_SEEKEND(f) (fseek((f), (long)0, SEEK_END)==0 ? SUCCEED : FAIL) +# define H5FI_TELL(f) (ftell(f)) +# define H5FI_OPENERR(f) ((f) == (FILE *)NULL) +# define H5FI_INVALID_FILE ((FILE *)NULL) +#endif /* FILELIB == POSIXBUFIO */ + +#if (FILELIB == POSIXUNBUFIO) +/* using POSIX unbuffered file I/O routines to access files */ +typedef int hdf_file_t; +# define H5FI_OPEN(p, a) (((a) & H5ACC_WRITE) ? open((p), O_RDWR) : open((p), O_RDONLY)) +# define H5FI_CREATE(p) (open((p), O_RDWR | O_CREAT | O_TRUNC)) +# define H5FI_CLOSE(f) (close(f)) +# define H5FI_FLUSH(f) (SUCCEED) +# define H5FI_READ(f, b, n) (((n)==read((f), (char *)(b), (n))) ? SUCCEED : FAIL) +# define H5FI_WRITE(f, b, n) (((n)==write((f), (char *)(b), (n))) ? SUCCEED : FAIL) +# define H5FI_SEEK(f, o) (lseek((f), (off_t)(o), SEEK_SET)!=(-1) ? SUCCEED : FAIL) +# define H5FI_SEEKEND(f) (lseek((f), (off_t)0, SEEK_END)!=(-1) ? SUCCEED : FAIL) +# define H5FI_TELL(f) (lseek((f), (off_t)0, SEEK_CUR)) +# define H5FI_OPENERR(f) (f < 0) +# define H5FI_INVALID_FILE ((int)-1) +#endif /* FILELIB == POSIXUNBUFIO */ + +#if (FILELIB == MACIO) +/* using special routines to redirect to Mac Toolkit I/O */ +typedef short hdf_file_t; +# define H5FI_OPEN(x,y) mopen(x,y) +# define H5FI_CREATE(name) mopen(name, H5ACC_CREATE) +# define H5FI_CLOSE(x) mclose(x) +# define H5FI_FLUSH(a) (SUCCEED) +# define H5FI_READ(a,b,c) mread(a, (char *) b, (int32) c) +# define H5FI_WRITE(a,b,c) mwrite(a, (char *) b, (int32) c) +# define H5FI_SEEK(x,y) mlseek(x, (int32 )y, 0) +# define H5FI_SEEKEND(x) mlseek(x, 0L, 2) +# define H5FI_TELL(x) mlseek(x,0L,1) +# define H5FI_OPENERR(f) (f < 0) +# define H5FI_INVALID_FILE ((short)-1) +#endif /* FILELIB == MACIO */ + +#if (FILELIB == WINNTIO) +/* using special Windows NT functions to enable reading/writing large chunks */ +typedef HFILE hdf_file_t; +# define H5FI_OPEN(p, a) (((a) & H5ACC_WRITE) ? _lopen((p), OF_READWRITE) : _lopen((p), OF_READ)) +# define H5FI_CREATE(p) (_lcreat((p), 0)) +# define H5FI_READ(f, b, n) (((int32)(n) == _hread((f), (b), (n))) ? SUCCEED : FAIL) +# define H5FI_WRITE(f, b, n) (((int32)(n) == _hwrite((f), (b), (n))) ? SUCCEED : FAIL) +# define H5FI_CLOSE(f) (_lclose(f)==0 ? SUCCEED : FAIL) +# define H5FI_FLUSH(f) (0) +# define H5FI_SEEK(f, o) (_llseek((f), (long)(o), 0)) +# define H5FI_SEEKEND(f) (_llseek((f), (long)0, 2)) +# define H5FI_TELL(f) (_llseek((f),0l,1)) +# define H5FI_OPENERR(f) ((f) == (HFILE)HFILE_ERROR) +# define H5FI_INVALID_FILE ((HFILE)HFILE_ERROR) +#endif /* FILELIB == WINNTIO */ + +#if (FILELIB == PAGEBUFIO) +#include "fmpio.h" +/* using page buffered file I/O routines to access files */ +typedef MPFILE *hdf_file_t; +# define H5FI_OPEN(p, a) (MPopen((p), (a))) +# define H5FI_CREATE(p) (MPopen((p), H5ACC_CREATE)) +# define H5FI_CLOSE(f) (MPclose(f)) +# define H5FI_FLUSH(f) (MPflush(f)) +# define H5FI_READ(f, b, n) (MPread((f), (char *)(b), (n))) +# define H5FI_WRITE(f, b, n) (MPwrite((f), (char *)(b), (n))) +# define H5FI_SEEK(f, o) (MPseek((f), (off_t)(o), SEEK_SET)) +# define H5FI_SEEKEND(f) (MPseek((f), (off_t)0, SEEK_END)) +# define H5FI_TELL(f) (MPseek((f), (off_t)0, SEEK_CUR)) +# define H5FI_OPENERR(f) ((f) == (MPFILE *)NULL) +# define H5FI_INVALID_FILE ((MPFILE *)NULL) +#endif /* FILELIB == PAGEBUFIO */ + +/************************************************************************** +* Allocation functions defined differently +**************************************************************************/ +#if !defined MALLOC_CHECK +# define HDmalloc(s) (malloc((size_t)s)) +# define HDcalloc(a,b) (calloc((size_t)a,(size_t)b)) +# define HDfree(p) (free((void*)p)) +# define HDrealloc(p,s) (realloc((void*)p,(size_t)s)) +#endif /* !defined MALLOC_CHECK */ +/* Macro to free space and clear pointer to NULL */ +#define HDfreenclear(p) { if((p)!=NULL) HDfree(p); p=NULL; } + +/************************************************************************** +* String functions defined differently +**************************************************************************/ + +# define HDstrcat(s1,s2) (strcat((s1),(s2))) +# define HDstrcmp(s,t) (strcmp((s),(t))) +# define HDstrcpy(s,d) (strcpy((s),(d))) +# define HDstrlen(s) (strlen((const char *)(s))) +# define HDstrncmp(s1,s2,n) (strncmp((s1),(s2),(n))) +# define HDstrncpy(s1,s2,n) (strncpy((s1),(s2),(n))) +# define HDstrchr(s,c) (strchr((s),(c))) +# define HDstrrchr(s,c) (strrchr((s),(c))) +# define HDstrtol(s,e,b) (strtol((s),(e),(b))) +/* non-standard function, not defined on the following mahcines - */ +#if !(defined VMS || defined macintosh || defined MAC || defined __MWERKS__ || defined SYMANTEC_C || defined MIPSEL || defined NEXT || defined CONVEX || defined IBM6000 || defined ANSISUN || defined IRIX) +# define HDstrdup(s) ((char *)strdup((const char *)(s))) +#endif /* !(VMS | etc..) */ + + +/************************************************************************** +* Memory functions defined differently +**************************************************************************/ + +# define HDmemcpy(dst,src,n) (memcpy((void *)(dst),(const void *)(src),(size_t)(n))) +# define HDmemmove(dst,src,n) (memmove((void*)(dst),(const void *)(src),(size_t)(n))) +# define HDmemset(dst,c,n) (memset((void *)(dst),(intn)(c),(size_t)(n))) +# define HDmemcmp(dst,src,n) (memcmp((const void *)(dst),(const void *)(src),(size_t)(n))) + + +/************************************************************************** +* Misc. functions +**************************************************************************/ +#if defined (MAC) || defined (macintosh) || defined(__MWERKS__) || defined (SYMANTEC_C) +#define HDstat(path, result) (mstat(path)) +#else /* !macintosh */ +#define HDstat(path, result) (stat(path, result)) +#endif /* !macintosh */ +#define HDgetcwd(s,l) (getcwd(s,l)) +#define HDgetenv(s1) (getenv(s1)) +#define HDputenv(s1) (putenv(s1)) +#define HDltoa(v) (ltoa(v)) +#if defined (SUN) && defined(__GNUC__) +#define HDatexit(f) (0) /* we punt on the SUN using gcc */ +#else /* !SUN & GCC */ +#define HDatexit(f) (atexit(f)) +#endif /* !SUN & GCC */ + +#endif /* HDF5PORT_H */ + diff --git a/src/hdf5type.h b/src/hdf5type.h new file mode 100644 index 0000000..ac5ffa3 --- /dev/null +++ b/src/hdf5type.h @@ -0,0 +1,70 @@ +/**************************************************************************** + * NCSA HDF * + * Software Development Group * + * National Center for Supercomputing Applications * + * University of Illinois at Urbana-Champaign * + * 605 E. Springfield, Champaign IL 61820 * + * * + * For conditions of distribution and use, see the accompanying * + * hdf/COPYING file. * + * * + ****************************************************************************/ + +/* $Id$ */ + +/* + * Header file for library-global generic typedefs + */ + +#ifndef HDF5TYPE_H +#define HDF5TYPE_H + +/* + * Define the standard error-value return type. This type should be used for + * functions which return SUCCEED/FAIL, instead of intn... + */ +typedef intn herr_t; /* Generic error-value type */ + +/* Object types for "meta" interface */ +typedef group_t hobjtype_t; /* Map the object in the "meta" interface to atom groups */ + +/* File-creation template information structure */ +typedef struct { + /* These object aren't ref. counted, I can't think of a good reason why you'd access each one more than once */ + /* uintn ref_count; Reference count for number of times object is accessed */ + uintn userblock_size; /* Size of the user block in the file in bytes */ + uintn offset_size; /* Number of bytes for offsets */ + uintn length_size; /* Number of bytes for lengths */ + uintn btree_page_size; /* Number of bytes for B-Tree pages */ + uint8 bootblock_ver; /* Version # of the bootblock */ + uint8 smallobject_ver; /* Version # of the small-object heap */ + uint8 freespace_ver; /* Version # of the free-space information */ + uint8 objectdir_ver; /* Version # of the object directory format */ + uint8 sharedheader_ver; /* Version # of the shared header format */ + } file_create_temp_t; + +/* Parameters to use when retrieving file-creation template information */ +typedef enum { + H5_USERBLOCK_SIZE, /* (uintn) Size of the user block in the file in bytes */ + H5_OFFSET_SIZE, /* (uintn) Number of bytes for offsets */ + H5_LENGTH_SIZE, /* (uintn) Number of bytes for lengths */ + H5_BTREE_SIZE, /* (uintn) Number of bytes for B-Tree pages */ + 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 */ + H5_OBJECTDIR_VER, /* (uint8) Version # of the object-directory format */ + H5_SHAREDHEADER_VER /* (uint8) Version # of the shared-header format */ + } file_create_param_t; + +/* HDF boolean type */ +typedef enum { + BFAIL=(-1), /* error value */ + BFALSE=0, + BTRUE=1 + } hbool_t; + +/* Unsigned integer error value (don't really know where else to put this - QAK) */ +#define UFAIL (unsigned)(-1) + +#endif /* HDF5TYPE_H */ + diff --git a/test/Makefile b/test/Makefile new file mode 100644 index 0000000..ec8bcf5 --- /dev/null +++ b/test/Makefile @@ -0,0 +1,50 @@ +### Name of target +TARGET = testhdf5 + +# +# PART 2: various choices +# + +### -DDEBUG Debugging options on +DEFS = -I../src + +################################################ +## no changes required below this line ## +################################################ + +INCL = ../src/hdf5.h testhdf5.h + +OBJ = testhdf5.o tmeta.o tfile.o theap.o + +LIBS = ../src/libhdf5.a + +$(TARGET): $(OBJ) $(LIBS) + $(CC) -o $(TARGET) $(OBJ) $(LIBS) + +all: $(TARGET) + +test: $(TARGET) + ./$(TARGET) + +debug: $(OBJ) + purify $(CC) -o $(TARGET) $(OBJ) $(LIBS) + +clean: + -rm -f *.o core *.core $(TARGET) + -rm -f *.bak *.h5 + +########################################################################### + +testhdf5.o: testhdf5.c $(INCL) + $(CC) $(CFLAGS) $(DEFS) testhdf5.c + +tmeta.o: tmeta.c $(INCL) + $(CC) $(CFLAGS) $(DEFS) tmeta.c + +tfile.o: tfile.c $(INCL) + $(CC) $(CFLAGS) $(DEFS) tfile.c + +theap.o: theap.c $(INCL) + $(CC) $(CFLAGS) $(DEFS) theap.c + + diff --git a/test/testhdf5.c b/test/testhdf5.c new file mode 100644 index 0000000..60959fa --- /dev/null +++ b/test/testhdf5.c @@ -0,0 +1,302 @@ +/**************************************************************************** + * NCSA HDF * + * Software Development Group * + * National Center for Supercomputing Applications * + * University of Illinois at Urbana-Champaign * + * 605 E. Springfield, Champaign IL 61820 * + * * + * For conditions of distribution and use, see the accompanying * + * hdf/COPYING file. * + * * + ****************************************************************************/ + +#ifdef RCSID +static char RcsId[] = "@(#)$Revision$"; +#endif + +/* $Id$ */ + +/* + FILE + testhdf5.c - HDF5 testing framework main file. + + REMARKS + General test wrapper for HDF5 base library test programs + + DESIGN + Each test function should be implemented as function having no + parameters and returning void (i.e. no return value). They should be put + into the list of InitTest() calls in main() below. Functions which depend + on other functionality should be placed below the InitTest() call for the + base functionality testing. + Each test module should include testhdf5.h and define a unique set of + names for test files they create. + + BUGS/LIMITATIONS + + EXPORTED ROUTINES/VARIABLES: + Two variables are exported: num_errs, and Verbosity. + + */ + +#if defined __MWERKS__ +#include <console.h> +#endif + +#define MAXNUMOFTESTS 30 +#define HDF5_TEST_MASTER + +/* Internal Variables */ +static int Index = 0; + +/* ANY new test needs to have a prototype in tproto.h */ +#include "testhdf5.h" + +struct TestStruct + { + int NumErrors; + char Description[64]; + int SkipFlag; + char Name[16]; + VOID (*Call) (void); + } + Test[MAXNUMOFTESTS]; + +static void InitTest(const char *TheName, VOID(*TheCall) (void), const char *TheDescr); +static void usage(void); + +static void InitTest(const char *TheName, VOID(*TheCall) (void), const char *TheDescr) +{ + if (Index >= MAXNUMOFTESTS) + { + print_func("Uh-oh, too many tests added, increase MAXNUMOFTEST!\n"); + exit(0); + } /* end if */ + HDstrcpy(Test[Index].Description, TheDescr); + HDstrcpy(Test[Index].Name, TheName); + Test[Index].Call = TheCall; + Test[Index].NumErrors = -1; + Test[Index].SkipFlag = 0; + Index++; +} + +static void usage(void) +{ + intn i; + + print_func("Usage: testhdf5 [-v[erbose] (l[ow]|m[edium]|h[igh]|0-10)] \n"); + print_func(" [-[e]x[clude] name+] \n"); + print_func(" [-o[nly] name+] \n"); + print_func(" [-b[egin] name] \n"); + print_func(" [-s[ummary]] \n"); + print_func(" [-c[leanoff]] \n"); + print_func(" [-n[ocaching]] \n"); + print_func(" [-h[elp]] \n"); + print_func("\n\n"); + print_func("verbose controls the amount of information displayed\n"); + print_func("exclude to exclude tests by name\n"); + print_func("only to name tests which should be run\n"); + print_func("begin start at the name of the test givin\n"); + print_func("summary prints a summary of test results at the end\n"); + print_func("cleanoff does not delete *.hdf files after execution of tests\n"); + print_func("nocaching do not turn on low-level DD caching\n"); + print_func("help print out this information\n"); + print_func("\n\n"); + print_func("This program currently tests the following: \n\n"); + print_func("%16s %s\n", "Name", "Description"); + print_func("%16s %s\n", "----", "-----------"); + for (i = 0; i < Index; i++) + print_func("%16s %s\n", Test[i].Name, Test[i].Description); + print_func("\n\n"); +} /* end usage() */ + +/* + * This routine is designed to provide equivalent functionality to 'printf' + * and allow easy replacement for environments which don't have stdin/stdout + * available. (i.e. Windows & the Mac) + */ +int print_func(const char *format, ...) +{ + va_list arglist; + int ret_value; + + va_start(arglist, format); + ret_value=vprintf(format, arglist); + va_end(arglist); + return(ret_value); +} + +int main(int argc, char *argv[]) +{ + int CLLoop; /* Command Line Loop */ + int Loop, Loop1; + int Summary = 0; + int CleanUp = 1; + int Cache = 1; + uintn major, minor, release, patch; + +#if defined __MWERKS__ + argc = ccommand(&argv); +#endif + +#if !(defined MAC || defined __MWERKS__ || defined SYMANTEC_C) + /* Un-buffer the stdout and stderr */ + setbuf(stderr, NULL); + setbuf(stdout, NULL); +#endif + + /* Tests are generally arranged from least to most complexity... */ + InitTest("metadata", test_metadata, "Encode/decode metadata code"); + InitTest("file", test_file, "Low-Level File I/O"); + InitTest("heap", test_heap, "Object and Name Heaps"); + + Verbosity = 4; /* Default Verbosity is Low */ + H5version(&major, &minor, &release, &patch); + + print_func("\nFor help use: testhdf5 -help\n"); + print_func("Built with HDF5 Library Version: %u.%ur%u, patch %u\n\n", (unsigned) major, + (unsigned) minor, (unsigned) release, (unsigned)patch); + for (CLLoop = 1; CLLoop < argc; CLLoop++) + { + if ((argc > CLLoop + 1) && ((HDstrcmp(argv[CLLoop], "-verbose") == 0) || + (HDstrcmp(argv[CLLoop], "-v") == 0))) + { + if (argv[CLLoop + 1][0] == 'l') + Verbosity = 4; + else if (argv[CLLoop + 1][0] == 'm') + Verbosity = 6; + else if (argv[CLLoop + 1][0] == 'h') + Verbosity = 10; + else + Verbosity = atoi(argv[CLLoop + 1]); + } /* end if */ + if ((argc > CLLoop) && ((HDstrcmp(argv[CLLoop], "-summary") == 0) || + (HDstrcmp(argv[CLLoop], "-s") == 0))) + Summary = 1; + + if ((argc > CLLoop) && ((HDstrcmp(argv[CLLoop], "-help") == 0) || + (HDstrcmp(argv[CLLoop], "-h") == 0))) + { + usage(); + exit(0); + } + + if ((argc > CLLoop) && ((HDstrcmp(argv[CLLoop], "-cleanoff") == 0) || + (HDstrcmp(argv[CLLoop], "-c") == 0))) + CleanUp = 0; + + if ((argc > CLLoop) && ((HDstrcmp(argv[CLLoop], "-nocache") == 0) || + (HDstrcmp(argv[CLLoop], "-n") == 0))) + Cache = 0; + + if ((argc > CLLoop + 1) && ((HDstrcmp(argv[CLLoop], "-exclude") == 0) || + (HDstrcmp(argv[CLLoop], "-x") == 0))) + { + Loop = CLLoop + 1; + while ((Loop < argc) && (argv[Loop][0] != '-')) + { + for (Loop1 = 0; Loop1 < Index; Loop1++) + if (HDstrcmp(argv[Loop], Test[Loop1].Name) == 0) + Test[Loop1].SkipFlag = 1; + Loop++; + } /* end while */ + } /* end if */ + if ((argc > CLLoop + 1) && ((HDstrcmp(argv[CLLoop], "-begin") == 0) || + (HDstrcmp(argv[CLLoop], "-b") == 0))) + { + Loop = CLLoop + 1; + while ((Loop < argc) && (argv[Loop][0] != '-')) + { + for (Loop1 = 0; Loop1 < Index; Loop1++) + { + if (HDstrcmp(argv[Loop], Test[Loop1].Name) != 0) + Test[Loop1].SkipFlag = 1; + if (HDstrcmp(argv[Loop], Test[Loop1].Name) == 0) + Loop1 = Index; + } /* end for */ + Loop++; + } /* end while */ + } /* end if */ + if ((argc > CLLoop + 1) && ((HDstrcmp(argv[CLLoop], "-only") == 0) || + (HDstrcmp(argv[CLLoop], "-o") == 0))) + { + for (Loop = 0; Loop < Index; Loop++) + Test[Loop].SkipFlag = 1; + Loop = CLLoop + 1; + while ((Loop < argc) && (argv[Loop][0] != '-')) + { + for (Loop1 = 0; Loop1 < Index; Loop1++) + if (HDstrcmp(argv[Loop], Test[Loop1].Name) == 0) + Test[Loop1].SkipFlag = 0; + Loop++; + } /* end while */ + } /* end if */ + } /* end for */ + +#ifdef NOT_YET + if(Cache) /* turn on caching, unless we were instucted not to */ + Hcache(CACHE_ALL_FILES,TRUE); +#endif /* NOT_YET */ + + for (Loop = 0; Loop < Index; Loop++) + { + if (Test[Loop].SkipFlag) + { + MESSAGE(2, print_func("Skipping -- %s \n", Test[Loop].Description); + ); + } + else + { + MESSAGE(2, print_func("Testing -- %s (%s) \n", Test[Loop].Description, + Test[Loop].Name); + ); + MESSAGE(5, print_func("===============================================\n"); + ); + Test[Loop].NumErrors = num_errs; + (*Test[Loop].Call) (); + Test[Loop].NumErrors = num_errs - Test[Loop].NumErrors; + MESSAGE(5, print_func("===============================================\n"); + ); + MESSAGE(5, print_func("There were %d errors detected.\n\n", (int) Test[Loop].NumErrors); + ); + } /* end else */ + } /* end for */ + + MESSAGE(2, print_func("\n\n"); + ) + if (num_errs) + print_func("!!! %d Error(s) were detected !!!\n\n", (int) num_errs); + else + print_func("All tests were successful. \n\n"); + + if (Summary) + { + print_func("Summary of Test Results:\n"); + print_func("Name of Test Errors Description of Test\n"); + print_func("---------------- ------ --------------------------------------\n"); + + for (Loop = 0; Loop < Index; Loop++) + { + if (Test[Loop].NumErrors == -1) + print_func("%16s %6s %s\n", Test[Loop].Name, "N/A", Test[Loop].Description); + else + print_func("%16s %6d %s\n", Test[Loop].Name, (int) Test[Loop].NumErrors, + Test[Loop].Description); + } /* end for */ + print_func("\n\n"); + } /* end if */ + + if (CleanUp) + { + MESSAGE(2, print_func("\nCleaning Up...\n\n"); + ); +#if !(defined DOS386 | defined WIN386) + system("rm -f *.hdf *.tmp"); +#else /* OLD_WAY */ + remove("*.hdf"); + remove("*.tmp"); +#endif /* OLD_WAY */ + } /* end if */ + exit(0); + return (0); +} /* end main() */ diff --git a/test/testhdf5.h b/test/testhdf5.h new file mode 100644 index 0000000..1b482d2 --- /dev/null +++ b/test/testhdf5.h @@ -0,0 +1,115 @@ +/**************************************************************************** + * NCSA HDF * + * Software Development Group * + * National Center for Supercomputing Applications * + * University of Illinois at Urbana-Champaign * + * 605 E. Springfield, Champaign IL 61820 * + * * + * For conditions of distribution and use, see the accompanying * + * hdf/COPYING file. * + * * + ****************************************************************************/ + +/* $Id$ */ + +/* + * This header file contains information required for testing the HDF5 library. + */ + +#ifndef HDF5TEST_H +#define HDF5TEST_H + +/* Include required headers */ +#include "hdf5.h" +#include <stdarg.h> + +/* Define these for use in all the tests */ +#ifndef HDF5_TEST_MASTER +extern +#endif +int num_errs +#ifdef HDF5_TEST_MASTER += 0 +#endif +, Verbosity +#ifdef HDF5_TEST_MASTER += 0 +#endif + ; + +/* Use %ld to print the value because long should cover most cases. */ +/* Used to make certain a return value _is_not_ a value */ +#define CHECK(ret, val, where) \ +do {if (Verbosity>9) print_func(" Call to routine: %15s at line %4d in %s returned %ld \n",where,(int)__LINE__,__FILE__,(long)ret);\ +if(ret == val) {print_func("*** UNEXPECTED RETURN from %s is %ld at line %4d in %s\n", where, (long)ret, (int)__LINE__,__FILE__); num_errs++;} \ +} while(0) + +#define CHECK_I(ret,where) { \ + if (Verbosity>9) { \ + print_func(" Call to routine: %15s at line %4d in %s returned %ld\n", \ + (where), (int)__LINE__, __FILE__, (long)(ret)); \ + if ((ret)<0) { \ + print_func ("*** UNEXPECTED RETURN from %s is %ld line %4d in %s\n", \ + (where), (long)(ret), (int)__LINE__, __FILE__); \ + num_errs++; \ + } \ + } \ +} + +#define CHECK_PTR(ret,where) { \ + if (Verbosity>9) { \ + print_func(" Call to routine: %15s at line %4d in %s returned %p\n", \ + (where), (int)__LINE__, __FILE__, (ret)); \ + if (!(ret)) { \ + print_func ("*** UNEXPECTED RETURN from %s is NULL line %4d in %s\n",\ + (where), (int)__LINE__, __FILE__); \ + num_errs++; \ + } \ + } \ +} + +/* Used to make certain a return value _is_ a value */ +#define VERIFY(x, val, where) \ +do {if (Verbosity>9) print_func(" Call to routine: %15s at line %4d in %s had value %ld \n",where,(int)__LINE__,__FILE__,(long)x);\ +if(x != val) {print_func("*** UNEXPECTED VALUE from %s is %ld at line %4d in %s\n", where, (long)x,(int)__LINE__,__FILE__); num_errs++;} \ +} while(0) + +/* Used to document process through a test and to check for errors */ +#define RESULT(ret,func) \ +do { \ +if (Verbosity>8) print_func(" Call to routine: %15s at line %4d in %s returned %ld \n",func,(int)__LINE__,__FILE__,(long)ret); \ +if (Verbosity>9) HEprint(stdout,0); \ +if(ret == FAIL) {print_func("*** UNEXPECTED RETURN from %s is %ld at line %4d in %s\n", func, (long)ret,(int)__LINE__,__FILE__); num_errs++;} \ +} while(0) + +/* Used to document process through a test */ +#define MESSAGE(v,a) {if (Verbosity>v) {a}} + +/* definitions for command strings */ +#define VERBOSITY_STR "Verbosity" +#define SKIP_STR "Skip" +#define TEST_STR "Test" +#define CLEAN_STR "Cleanup" + +/* System command to use for Cleanup */ +#ifdef VMS +#define CLEAN_CMD "delete *.hdf;*" +#else +# ifdef WIN32 +# define CLEAN_CMD "del *.hdf" +# else +/* default is Unix */ +# define CLEAN_CMD "rm -f *.hdf" +# endif /* WIN32 */ +#endif /*VMS */ + +/* Prototypes for the support routines */ +int print_func(const char *, ...); + +/* Prototypes for the test routines */ +void test_metadata(void); +void test_file(void); +void test_heap (void); + +#endif /* HDF5TEST_H */ + diff --git a/test/tfile.c b/test/tfile.c new file mode 100644 index 0000000..81c8cd2 --- /dev/null +++ b/test/tfile.c @@ -0,0 +1,288 @@ +/**************************************************************************** + * NCSA HDF * + * Software Development Group * + * National Center for Supercomputing Applications * + * University of Illinois at Urbana-Champaign * + * 605 E. Springfield, Champaign IL 61820 * + * * + * For conditions of distribution and use, see the accompanying * + * hdf/COPYING file. * + * * + ****************************************************************************/ + +#ifdef RCSID +static char RcsId[] = "$Revision$"; +#endif + +/* $Id$ */ + +/*********************************************************** +* +* Test program: tfile +* +* Test the low-level file I/O features. +* +*************************************************************/ + +#include "testhdf5.h" + +#define F1_USERBLOCK_SIZE HDF5_USERBLOCK_DEFAULT +#define F1_OFFSET_SIZE HDF5_OFFSETSIZE_DEFAULT +#define F1_LENGTH_SIZE HDF5_LENGTHSIZE_DEFAULT +#define F1_BTREEPAGE_SIZE HDF5_BTREEPAGE_DEFAULT +#define FILE1 "tfile1.h5" + +#define F2_USERBLOCK_SIZE 512 +#define F2_OFFSET_SIZE 8 +#define F2_LENGTH_SIZE 8 +#define F2_BTREEPAGE_SIZE 2048 +#define FILE2 "tfile2.h5" + +#define F3_USERBLOCK_SIZE HDF5_USERBLOCK_DEFAULT +#define F3_OFFSET_SIZE F2_OFFSET_SIZE +#define F3_LENGTH_SIZE F2_LENGTH_SIZE +#define F3_BTREEPAGE_SIZE F2_BTREEPAGE_SIZE +#define FILE3 "tfile3.h5" + +/**************************************************************** +** +** test_file_create(): Low-level file creation I/O test routine. +** +****************************************************************/ +static void test_file_create(void) +{ + hatom_t fid1,fid2,fid3; /* HDF5 File IDs */ + hatom_t tmpl1,tmpl2; /* File creation templates */ + uintn parm; /* File-creation parameters */ + herr_t ret; /* Generic return value */ + + /* Output message about test being performed */ + MESSAGE(5, print_func("Testing Low-Level File Creation I/O\n");); + + /* Create first file */ + fid1=H5Fcreate(FILE1,H5ACC_OVERWRITE,0,0); + CHECK(fid1,FAIL,"H5Fcreate"); + + /* Try to create first file again (should fail) */ + fid2=H5Fcreate(FILE1,H5ACC_OVERWRITE,0,0); + VERIFY(fid2,FAIL,"H5Fcreate"); + + /* Get the file-creation template */ + tmpl1=H5Fget_create_template(fid1); + CHECK(tmpl1,FAIL,"H5Fget_create_template"); + + /* Get the file-creation parameters */ + ret=H5Cgetparm(tmpl1,H5_USERBLOCK_SIZE,&parm); +printf("USERBLOCK_SIZE=%u\n",parm); + CHECK(ret,FAIL,"H5Cgetparm"); + VERIFY(parm,F1_USERBLOCK_SIZE,"H5Cgetparm"); + + ret=H5Cgetparm(tmpl1,H5_OFFSET_SIZE,&parm); +printf("OFFSET_SIZE=%u\n",parm); + CHECK(ret,FAIL,"H5Cgetparm"); + VERIFY(parm,F1_OFFSET_SIZE,"H5Cgetparm"); + + ret=H5Cgetparm(tmpl1,H5_LENGTH_SIZE,&parm); +printf("LENGTH_SIZE=%u\n",parm); + CHECK(ret,FAIL,"H5Cgetparm"); + VERIFY(parm,F1_LENGTH_SIZE,"H5Cgetparm"); + + ret=H5Cgetparm(tmpl1,H5_BTREE_SIZE,&parm); +printf("BTREE_SIZE=%u\n",parm); + CHECK(ret,FAIL,"H5Cgetparm"); + VERIFY(parm,F1_BTREEPAGE_SIZE,"H5Cgetparm"); + + /* Release file-creation template */ + ret=H5Mrelease(tmpl1); + CHECK(ret,FAIL,"H5Mrelease"); + + /* Double-check that the atom has been vaporized */ + ret=H5Mrelease(tmpl1); + VERIFY(ret,FAIL,"H5Mrelease"); + + /* Create a new file with a non-standard file-creation template */ + tmpl1=H5Mcreate(fid1,H5_TEMPLATE,NULL); + CHECK(tmpl1,FAIL,"H5Mcreate"); + + /* Set the new file-creation parameters */ + parm=F2_USERBLOCK_SIZE; + ret=H5Csetparm(tmpl1,H5_USERBLOCK_SIZE,&parm); + CHECK(ret,FAIL,"H5Csetparm"); + + parm=F2_OFFSET_SIZE; + ret=H5Csetparm(tmpl1,H5_OFFSET_SIZE,&parm); + CHECK(ret,FAIL,"H5Csetparm"); + + parm=F2_LENGTH_SIZE; + ret=H5Csetparm(tmpl1,H5_LENGTH_SIZE,&parm); + CHECK(ret,FAIL,"H5Csetparm"); + + parm=F2_BTREEPAGE_SIZE; + ret=H5Csetparm(tmpl1,H5_BTREE_SIZE,&parm); + CHECK(ret,FAIL,"H5Csetparm"); + + /* Try to create second file, with non-standard file-creation template params */ + fid2=H5Fcreate(FILE2,H5ACC_OVERWRITE,tmpl1,0); + CHECK(fid2,FAIL,"H5Fcreate"); + + /* Release file-creation template */ + ret=H5Mrelease(tmpl1); + CHECK(ret,FAIL,"H5Mrelease"); + + /* Get the file-creation template */ + tmpl1=H5Fget_create_template(fid2); + CHECK(tmpl1,FAIL,"H5Fget_create_template"); + + /* Get the file-creation parameters */ + ret=H5Cgetparm(tmpl1,H5_USERBLOCK_SIZE,&parm); +printf("USERBLOCK_SIZE=%u\n",parm); + CHECK(ret,FAIL,"H5Cgetparm"); + VERIFY(parm,F2_USERBLOCK_SIZE,"H5Cgetparm"); + + ret=H5Cgetparm(tmpl1,H5_OFFSET_SIZE,&parm); +printf("OFFSET_SIZE=%u\n",parm); + CHECK(ret,FAIL,"H5Cgetparm"); + VERIFY(parm,F2_LENGTH_SIZE,"H5Cgetparm"); + + ret=H5Cgetparm(tmpl1,H5_LENGTH_SIZE,&parm); +printf("LENGTH_SIZE=%u\n",parm); + CHECK(ret,FAIL,"H5Cgetparm"); + VERIFY(parm,F2_OFFSET_SIZE,"H5Cgetparm"); + + ret=H5Cgetparm(tmpl1,H5_BTREE_SIZE,&parm); +printf("BTREE_SIZE=%u\n",parm); + CHECK(ret,FAIL,"H5Cgetparm"); + VERIFY(parm,F2_BTREEPAGE_SIZE,"H5Cgetparm"); + + /* Clone the file-creation template */ + tmpl2=H5Mcopy(tmpl1); + CHECK(tmpl2,FAIL,"H5Mcopy"); + + /* Release file-creation template */ + ret=H5Mrelease(tmpl1); + CHECK(ret,FAIL,"H5Mrelease"); + + /* Set the new file-creation parameter */ + parm=F3_USERBLOCK_SIZE; + ret=H5Csetparm(tmpl2,H5_USERBLOCK_SIZE,&parm); + CHECK(ret,FAIL,"H5Csetparm"); + + /* Try to create second file, with non-standard file-creation template params */ + fid3=H5Fcreate(FILE3,H5ACC_OVERWRITE,tmpl2,0); + CHECK(fid3,FAIL,"H5Fcreate"); + + /* Release file-creation template */ + ret=H5Mrelease(tmpl2); + CHECK(ret,FAIL,"H5Mrelease"); + + /* Get the file-creation template */ + tmpl1=H5Fget_create_template(fid3); + CHECK(tmpl1,FAIL,"H5Fget_create_template"); + + /* Get the file-creation parameters */ + ret=H5Cgetparm(tmpl1,H5_USERBLOCK_SIZE,&parm); +printf("USERBLOCK_SIZE=%u\n",parm); + CHECK(ret,FAIL,"H5Cgetparm"); + VERIFY(parm,F3_USERBLOCK_SIZE,"H5Cgetparm"); + + ret=H5Cgetparm(tmpl1,H5_OFFSET_SIZE,&parm); +printf("OFFSET_SIZE=%u\n",parm); + CHECK(ret,FAIL,"H5Cgetparm"); + VERIFY(parm,F3_LENGTH_SIZE,"H5Cgetparm"); + + ret=H5Cgetparm(tmpl1,H5_LENGTH_SIZE,&parm); +printf("LENGTH_SIZE=%u\n",parm); + CHECK(ret,FAIL,"H5Cgetparm"); + VERIFY(parm,F3_OFFSET_SIZE,"H5Cgetparm"); + + ret=H5Cgetparm(tmpl1,H5_BTREE_SIZE,&parm); +printf("BTREE_SIZE=%u\n",parm); + CHECK(ret,FAIL,"H5Cgetparm"); + VERIFY(parm,F3_BTREEPAGE_SIZE,"H5Cgetparm"); + + /* Release file-creation template */ + ret=H5Mrelease(tmpl1); + CHECK(ret,FAIL,"H5Mrelease"); + + /* Close first file */ + ret=H5Fclose(fid1); + CHECK(ret,FAIL,"H5Fclose"); + + /* Close second file */ + ret=H5Fclose(fid2); + CHECK(ret,FAIL,"H5Fclose"); + + /* Close third file */ + ret=H5Fclose(fid3); + CHECK(ret,FAIL,"H5Fclose"); +} /* test_file_create() */ + + +/**************************************************************** +** +** test_file_open(): Low-level file open I/O test routine. +** +****************************************************************/ +static void test_file_open(void) +{ + hatom_t fid1,fid2,fid3; /* HDF5 File IDs */ + hatom_t tmpl1,tmpl2; /* File creation templates */ + uintn parm; /* File-creation parameters */ + herr_t ret; /* Generic return value */ + + /* Output message about test being performed */ + MESSAGE(5, print_func("Testing Low-Level File Opening I/O\n");); + + /* Open second file */ + fid1=H5Fopen(FILE2,H5ACC_WRITE,0); + CHECK(fid1,FAIL,"H5Fooen"); + + /* Get the file-creation template */ + tmpl1=H5Fget_create_template(fid1); + CHECK(tmpl1,FAIL,"H5Fget_create_template"); + + /* Get the file-creation parameters */ + ret=H5Cgetparm(tmpl1,H5_USERBLOCK_SIZE,&parm); +printf("USERBLOCK_SIZE=%u\n",parm); + CHECK(ret,FAIL,"H5Cgetparm"); + VERIFY(parm,F2_USERBLOCK_SIZE,"H5Cgetparm"); + + ret=H5Cgetparm(tmpl1,H5_OFFSET_SIZE,&parm); +printf("OFFSET_SIZE=%u\n",parm); + CHECK(ret,FAIL,"H5Cgetparm"); + VERIFY(parm,F2_OFFSET_SIZE,"H5Cgetparm"); + + ret=H5Cgetparm(tmpl1,H5_LENGTH_SIZE,&parm); +printf("LENGTH_SIZE=%u\n",parm); + CHECK(ret,FAIL,"H5Cgetparm"); + VERIFY(parm,F2_LENGTH_SIZE,"H5Cgetparm"); + + ret=H5Cgetparm(tmpl1,H5_BTREE_SIZE,&parm); +printf("BTREE_SIZE=%u\n",parm); + CHECK(ret,FAIL,"H5Cgetparm"); + VERIFY(parm,F2_BTREEPAGE_SIZE,"H5Cgetparm"); + + /* Release file-creation template */ + ret=H5Mrelease(tmpl1); + CHECK(ret,FAIL,"H5Mrelease"); + + /* Close first file */ + ret=H5Fclose(fid1); + CHECK(ret,FAIL,"H5Fclose"); +} /* test_file_open() */ + + +/**************************************************************** +** +** test_file(): Main low-level file I/O test routine. +** +****************************************************************/ +void test_file(void) +{ + /* Output message about test being performed */ + MESSAGE(5, print_func("Testing Low-Level File I/O\n");); + + test_file_create(); /* Test file creation (also creation templates) */ + test_file_open(); /* Test file opening */ +} /* test_file() */ + diff --git a/test/theap.c b/test/theap.c new file mode 100644 index 0000000..41a9cbc --- /dev/null +++ b/test/theap.c @@ -0,0 +1,87 @@ +/*------------------------------------------------------------------------- + * Copyright (C) 1997 National Center for Supercomputing Applications. + * All rights reserved. + * + *------------------------------------------------------------------------- + * + * Created: theap.c + * Jul 17 1997 + * Robb Matzke <robb@maya.nuance.com> + * + * Purpose: + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +#include "testhdf5.h" + +#include "H5ACprivate.h" +#include "H5Fprivate.h" +#include "H5Hprivate.h" + +#define NOBJS 40 + + +/*------------------------------------------------------------------------- + * Function: test_heap + * + * Purpose: Test name and object heaps. + * + * Return: void + * + * Programmer: Robb Matzke + * robb@maya.nuance.com + * Jul 17 1997 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +void +test_heap (void) +{ + int i, j; + hatom_t fid; + hdf5_file_t *f; + off_t heap; + char buf[NOBJS+8]; + const char *s; + off_t obj[NOBJS]; + + MESSAGE (5, print_func("Testing Heaps\n");); + + /* Create the file */ + fid = H5Fcreate ("theap.h5", H5ACC_OVERWRITE, 0, 0); + CHECK (fid, FAIL, "H5Fcreate"); + f = H5Aatom_object (fid); + CHECK (f, NULL, "H5Aatom_object"); + + /* Create a new heap */ + heap = H5H_new (f, 0); + CHECK_I (heap, "H5H_new"); + + /* Add stuff to the heap */ + for (i=0; i<NOBJS; i++) { + fprintf (stderr, "%d\n", i); + sprintf (buf, "%03d-", i); + for (j=4; j<i; j++) buf[j] = '0' + j%10; + if (j>4) buf[j] = '\0'; + + obj[i] = H5H_insert (f, heap, strlen(buf)+1, buf); + CHECK_I (heap, "H5H_insert"); + } + + /* Flush the cache and invalidate everything */ + H5AC_flush (f, NULL, 0, TRUE); + + /* Read the objects back out */ + for (i=0; i<NOBJS; i++) { + s = H5H_peek (f, heap, obj[i]); + print_func ("object is `%s'\n", s); + } + + /* Close the file */ + H5Fclose (fid); +} + diff --git a/test/tmeta.c b/test/tmeta.c new file mode 100644 index 0000000..7ef7d73 --- /dev/null +++ b/test/tmeta.c @@ -0,0 +1,120 @@ +/**************************************************************************** + * NCSA HDF * + * Software Development Group * + * National Center for Supercomputing Applications * + * University of Illinois at Urbana-Champaign * + * 605 E. Springfield, Champaign IL 61820 * + * * + * For conditions of distribution and use, see the accompanying * + * hdf/COPYING file. * + * * + ****************************************************************************/ + +#ifdef RCSID +static char RcsId[] = "$Revision$"; +#endif + +/* $Id$ */ + +/*********************************************************** +* +* Test program: tmeta +* +* Test the basic meta-data encode/decode macros calls. +* +*************************************************************/ + +#include "testhdf5.h" + +#define TEST_INT16_VALUE -7641 +#define TEST_UINT16_VALUE 45002 +#define TEST_INT32_VALUE -981236 +#define TEST_UINT32_VALUE 3476589 + +uint8 compar_buffer[]={ + /* Little-endian encoded version of the 16-bit signed integer */ + (uint8)((TEST_INT16_VALUE)&0xff), (uint8)((TEST_INT16_VALUE>>8)&0xff), + /* Little-endian encoded version of the 16-bit unsigned integer */ + (uint8)((TEST_UINT16_VALUE)&0xff), (uint8)((TEST_UINT16_VALUE>>8)&0xff), + /* Little-endian encoded version of the 32-bit signed integer */ + (uint8)((TEST_INT32_VALUE)&0xff), (uint8)((TEST_INT32_VALUE>>8)&0xff), + (uint8)((TEST_INT32_VALUE>>16)&0xff), (uint8)((TEST_INT32_VALUE>>24)&0xff), + /* Little-endian encoded version of the 32-bit unsigned integer */ + (uint8)((TEST_UINT32_VALUE)&0xff), (uint8)((TEST_UINT32_VALUE>>8)&0xff), + (uint8)((TEST_UINT32_VALUE>>16)&0xff), (uint8)((TEST_UINT32_VALUE>>24)&0xff), + }; + +uint8 encode_buffer[sizeof(compar_buffer)]; + +/**************************************************************** +** +** test_metadata(): Main meta-data encode/decode testing routine. +** +****************************************************************/ +void test_metadata(void) +{ + int16 ei16=TEST_INT16_VALUE; /* variables to hold the values to encode */ + uint16 eu16=TEST_UINT16_VALUE; + int32 ei32=TEST_INT32_VALUE; + uint32 eu32=TEST_UINT32_VALUE; + int16 di16; /* variables to hold the decoded values */ + uint16 du16; + int32 di32; + uint32 du32; + uint8 *p; /* pointer into the buffer being en/de-coded */ + + /* Output message about test being performed */ + MESSAGE(5, print_func("Testing Metadata encode/decode code\n");); + + /* Start by encoding the values above */ + p=encode_buffer; + INT16ENCODE(p,ei16); /* Encode the int16 value */ + UINT16ENCODE(p,eu16); /* Encode the uint16 value */ + INT32ENCODE(p,ei32); /* Encode the int32 value */ + UINT32ENCODE(p,eu32); /* Encode the uint32 value */ + + /* Check if we got what we asked for */ + if(HDmemcmp(encode_buffer,compar_buffer,sizeof(compar_buffer))!=0) + { + uintn u; /* local counting variable */ + + for(u=0; u<sizeof(compar_buffer); u++) + { + if(compar_buffer[u]!=encode_buffer[u]) + { + print_func("Error encoding meta-data at offset %u, wanted: %u, got: %u\n",(unsigned)u,(unsigned)compar_buffer[u],(unsigned)encode_buffer[u]); + num_errs++; + } /* end if */ + } /* end for */ + } /* end if */ + + /* Test decoding macros */ + p=encode_buffer; + INT16DECODE(p,di16); /* Decode the int16 value */ + UINT16DECODE(p,du16); /* Decode the uint16 value */ + INT32DECODE(p,di32); /* Decode the int32 value */ + UINT32DECODE(p,du32); /* Decode the uint32 value */ + + /* Check the values decoded */ + if(di16!=TEST_INT16_VALUE) + { + print_func("Error decoding int16 meta-data wanted: %d, got: %d\n",(int)TEST_INT16_VALUE,(int)di16); + num_errs++; + } /* end if */ + if(du16!=TEST_UINT16_VALUE) + { + print_func("Error decoding uint16 meta-data wanted: %u, got: %u\n",(unsigned)TEST_UINT16_VALUE,(unsigned)du16); + num_errs++; + } /* end if */ + if(di32!=TEST_INT32_VALUE) + { + print_func("Error decoding int32 meta-data wanted: %ld, got: %ld\n",(long)TEST_INT32_VALUE,(long)di32); + num_errs++; + } /* end if */ + if(du32!=TEST_UINT32_VALUE) + { + print_func("Error decoding uint32 meta-data wanted: %lu, got: %lu\n",(unsigned long)TEST_UINT32_VALUE,(unsigned long)du32); + num_errs++; + } /* end if */ +} /* test_metadata() */ + |