From d9239fdd88e3fcd4ed9ad5b4798510c202b28e21 Mon Sep 17 00:00:00 2001 From: Achim Gsell Date: Thu, 22 Nov 2007 11:08:23 +0000 Subject: [PATCH] src/h5/errorhandling.c src/h5/u_readwrite.h src/h5/H5.h src/h5/errorhandling.h src/h5/readwrite.c src/h5/openclose.c src/h5/attribs.c src/h5/Makefile.am src/h5/u_readwrite.c src/h5/readwrite.h src/h5/openclose.h src/h5/attribs.h * added --- .gitattributes | 12 + src/h5/H5.h | 10 + src/h5/Makefile.am | 76 ++++++ src/h5/attribs.c | 163 ++++++++++++ src/h5/attribs.h | 36 +++ src/h5/errorhandling.c | 224 ++++++++++++++++ src/h5/errorhandling.h | 118 +++++++++ src/h5/openclose.c | 436 +++++++++++++++++++++++++++++++ src/h5/openclose.h | 37 +++ src/h5/readwrite.c | 299 ++++++++++++++++++++++ src/h5/readwrite.h | 64 +++++ src/h5/u_readwrite.c | 563 +++++++++++++++++++++++++++++++++++++++++ src/h5/u_readwrite.h | 64 +++++ 13 files changed, 2102 insertions(+) create mode 100644 src/h5/H5.h create mode 100644 src/h5/Makefile.am create mode 100644 src/h5/attribs.c create mode 100644 src/h5/attribs.h create mode 100644 src/h5/errorhandling.c create mode 100644 src/h5/errorhandling.h create mode 100644 src/h5/openclose.c create mode 100644 src/h5/openclose.h create mode 100644 src/h5/readwrite.c create mode 100644 src/h5/readwrite.h create mode 100644 src/h5/u_readwrite.c create mode 100644 src/h5/u_readwrite.h diff --git a/.gitattributes b/.gitattributes index f374358..a5c6012 100644 --- a/.gitattributes +++ b/.gitattributes @@ -38,6 +38,18 @@ src/bindings/Fortran/H5PartF.c -text src/bindings/Fortran/H5PartF90.inc -text src/bindings/Fortran/TestUnderscore.f -text src/bindings/Fortran/TestUnderscoreC.c -text +src/h5/H5.h -text +src/h5/Makefile.am -text +src/h5/attribs.c -text +src/h5/attribs.h -text +src/h5/errorhandling.c -text +src/h5/errorhandling.h -text +src/h5/openclose.c -text +src/h5/openclose.h -text +src/h5/readwrite.c -text +src/h5/readwrite.h -text +src/h5/u_readwrite.c -text +src/h5/u_readwrite.h -text test/Bench.c -text test/BlockTestSpecs.txt -text test/H5BlockDissolveGhosts.c -text diff --git a/src/h5/H5.h b/src/h5/H5.h new file mode 100644 index 0000000..d4420e7 --- /dev/null +++ b/src/h5/H5.h @@ -0,0 +1,10 @@ +#ifndef __H5_H +#define __H5_H + +#include "attribs.h" +#include "errorhandling.h" +#include "openclose.h" +#include "readwrite.h" +#include "u_readwrite.h" + +#endif diff --git a/src/h5/Makefile.am b/src/h5/Makefile.am new file mode 100644 index 0000000..849cdde --- /dev/null +++ b/src/h5/Makefile.am @@ -0,0 +1,76 @@ +# src level Makefile.am + +# PATH SETTING (IMPORTED FROM CONFIGURE) +HDF5ROOT = @HDF5ROOT@ + +OBJEXT = o + + + + +# COMPILERS +CC = @CC@ + +#INCLUDES +HDFINC = -I$(HDF5ROOT)/include +MPIINC = @MPIINC@ + +INC = $(HDFINC) ${MPIINC} -I../ + +# H5Part header file location +H5PINC = -I@prefix@/include + +# COMPILER FLAGS +CFLAGS = @CFLAGS@ ${INC} + +# H5Part compiled library location +H5PLIB = -L@prefix@/lib + +# HDF5 LIBRARY +HDFLIB = -L$(HDF5ROOT)/lib -lhdf5 -lz $(SZLIB) @LDFLAGS@ + +# SZ LIBRARY +SZLIB = @SZLIB@ + +# Extra files that I wish to include in the dist tar ball. +EXTRA_DIST = $(EXTRA_HEADERS) + +# Files that I don't want to include in the dist tar ball +nodist_include_HEADERS = + +# What to build... Will be determined by configure script. +lib_LIBRARIES = libH5.a + +# Listing of all possible targets that I may build. +EXTRA_LIBRARIES = libH5.a + +# Header files that I wish to install in $(prefix)/include +include_HEADERS = H5.h + +# Listing of all possible headers that I may include +EXTRA_HEADERS = + +# Listing of sources +libH5_a_SOURCES = attribs.c errorhandling.c openclose.c readwrite.c u_readwrite.c + +all: libH5.a + +libH5.a: $(libH5_a_OBJECTS) + echo $(libH5_a_OBJECTS) + ${AR} rucs $@ $^ + +%.o : %.c + $(CC) $(CFLAGS) $(INC) -c $< + +$(libH5_a_OBJECTS): H5.h + +errorhandling.o: errorhandling.c + +clean: + $(RM) -f *~ *.o *.a *.so + +distclean: clean + $(RM) -f *.a + $(RM) -rf .deps + $(RM) -rf .libs + $(RM) -f Makefile diff --git a/src/h5/attribs.c b/src/h5/attribs.c new file mode 100644 index 0000000..bc7cf4c --- /dev/null +++ b/src/h5/attribs.c @@ -0,0 +1,163 @@ +#include +#include +#include /* va_arg - System dependent ?! */ +#include +#include +#include +#include + +#include "H5PartTypes.h" +#include "H5BlockTypes.h" +#include "H5Part.h" +#include "H5Block.h" +#include "H5PartPrivate.h" +#include "H5BlockPrivate.h" +#include "H5PartErrors.h" +#include "H5BlockErrors.h" +#include "H5.h" + + +h5part_int64_t +H5_read_attrib ( + hid_t id, + const char *attrib_name, + void *attrib_value + ) { + + herr_t herr; + hid_t attrib_id; + hid_t space_id; + hid_t type_id; + hid_t mytype; + hsize_t nelem; + + attrib_id = H5Aopen_name ( id, attrib_name ); + if ( attrib_id <= 0 ) return HANDLE_H5A_OPEN_NAME_ERR( attrib_name ); + + mytype = H5Aget_type ( attrib_id ); + if ( mytype < 0 ) return HANDLE_H5A_GET_TYPE_ERR; + + space_id = H5Aget_space ( attrib_id ); + if ( space_id < 0 ) return HANDLE_H5A_GET_SPACE_ERR; + + nelem = H5Sget_simple_extent_npoints ( space_id ); + if ( nelem < 0 ) return HANDLE_H5S_GET_SIMPLE_EXTENT_NPOINTS_ERR; + + type_id = H5_normalize_h5_type ( mytype ); + + herr = H5Aread (attrib_id, type_id, attrib_value ); + if ( herr < 0 ) return HANDLE_H5A_READ_ERR; + + herr = H5Sclose ( space_id ); + if ( herr < 0 ) return HANDLE_H5S_CLOSE_ERR; + + herr = H5Tclose ( mytype ); + if ( herr < 0 ) return HANDLE_H5T_CLOSE_ERR; + + herr = H5Aclose ( attrib_id ); + if ( herr < 0 ) return HANDLE_H5A_CLOSE_ERR; + + return H5PART_SUCCESS; +} + +h5part_int64_t +H5_write_attrib ( + hid_t id, + const char *attrib_name, + const hid_t attrib_type, + const void *attrib_value, + const hsize_t attrib_nelem + ) { + + herr_t herr; + hid_t space_id; + hid_t attrib_id; + + space_id = H5Screate_simple (1, &attrib_nelem, NULL); + if ( space_id < 0 ) + return HANDLE_H5S_CREATE_SIMPLE_ERR ( attrib_nelem ); + + attrib_id = H5Acreate ( + id, + attrib_name, + attrib_type, + space_id, + H5P_DEFAULT ); + if ( attrib_id < 0 ) return HANDLE_H5A_CREATE_ERR ( attrib_name ); + + herr = H5Awrite ( attrib_id, attrib_type, attrib_value); + if ( herr < 0 ) return HANDLE_H5A_WRITE_ERR ( attrib_name ); + + herr = H5Aclose ( attrib_id ); + if ( herr < 0 ) return HANDLE_H5A_CLOSE_ERR; + + herr = H5Sclose ( space_id ); + if ( herr < 0 ) return HANDLE_H5S_CLOSE_ERR; + + return H5PART_SUCCESS; +} + +h5part_int64_t +H5_get_attrib_info ( + hid_t id, + const h5part_int64_t attrib_idx, + char *attrib_name, + const h5part_int64_t len_attrib_name, + h5part_int64_t *attrib_type, + h5part_int64_t *attrib_nelem + ) { + + herr_t herr; + hid_t attrib_id; + hid_t mytype; + hid_t space_id; + + attrib_id = H5Aopen_idx ( id, (unsigned int)attrib_idx ); + if ( attrib_id < 0 ) return HANDLE_H5A_OPEN_IDX_ERR ( attrib_idx ); + + if ( attrib_nelem ) { + space_id = H5Aget_space ( attrib_id ); + if ( space_id < 0 ) return HANDLE_H5A_GET_SPACE_ERR; + + *attrib_nelem = H5Sget_simple_extent_npoints ( space_id ); + if ( *attrib_nelem < 0 ) + return HANDLE_H5S_GET_SIMPLE_EXTENT_NPOINTS_ERR; + + herr = H5Sclose ( space_id ); + if ( herr < 0 ) return HANDLE_H5S_CLOSE_ERR; + } + if ( attrib_name ) { + herr = H5Aget_name ( + attrib_id, + (size_t)len_attrib_name, + attrib_name ); + if ( herr < 0 ) return HANDLE_H5A_GET_NAME_ERR; + } + if ( attrib_type ) { + mytype = H5Aget_type ( attrib_id ); + if ( mytype < 0 ) return HANDLE_H5A_GET_TYPE_ERR; + + *attrib_type = H5_normalize_h5_type ( mytype ); + + herr = H5Tclose ( mytype ); + if ( herr < 0 ) return HANDLE_H5T_CLOSE_ERR; + } + herr = H5Aclose ( attrib_id); + if ( herr < 0 ) return HANDLE_H5A_CLOSE_ERR; + + return H5PART_SUCCESS; +} + +h5part_int64_t +H5_get_num_attribs ( + H5PartFile *f, + hid_t id + ) { + + CHECK_FILEHANDLE ( f ); + + int nattribs = H5Aget_num_attrs ( id ); + if ( nattribs < 0 ) HANDLE_H5A_GET_NUM_ATTRS_ERR; + + return (h5part_int64_t) nattribs; +} diff --git a/src/h5/attribs.h b/src/h5/attribs.h new file mode 100644 index 0000000..e1bc789 --- /dev/null +++ b/src/h5/attribs.h @@ -0,0 +1,36 @@ +#ifndef __ATTRIBS_H +#define __ATTRIBS_H + +h5part_int64_t +H5_read_attrib ( + hid_t id, + const char *attrib_name, + void *attrib_value + ); + +h5part_int64_t +H5_write_attrib ( + hid_t id, + const char *attrib_name, + const hid_t attrib_type, + const void *attrib_value, + const hsize_t attrib_nelem + ); + +h5part_int64_t +H5_get_attrib_info ( + hid_t id, + const h5part_int64_t attrib_idx, + char *attrib_name, + const h5part_int64_t len_attrib_name, + h5part_int64_t *attrib_type, + h5part_int64_t *attrib_nelem + ); + +h5part_int64_t +H5_get_num_attribs ( + H5PartFile *f, + hid_t id + ); + +#endif diff --git a/src/h5/errorhandling.c b/src/h5/errorhandling.c new file mode 100644 index 0000000..9ff4e9d --- /dev/null +++ b/src/h5/errorhandling.c @@ -0,0 +1,224 @@ +#include +#include +#include /* va_arg - System dependent ?! */ +#include +#include +#include +#include + +#include "H5PartTypes.h" +#include "H5Part.h" +#include "H5PartPrivate.h" +#include "H5PartErrors.h" +#include "H5.h" + +h5part_error_handler _err_handler = H5PartReportErrorHandler; +h5part_int64_t _h5part_errno = H5PART_SUCCESS; +h5part_int64_t _debug = 0; + +static char *__funcname = "NONE"; + +h5part_int64_t +H5_set_debuglevel ( + h5part_int64_t level + ) { + _debug = level; + return H5PART_SUCCESS; +} + +h5part_int64_t +H5_get_debuglevel ( + void + ) { + return _debug; +} + +h5part_int64_t +H5_set_errorhandler ( + h5part_error_handler handler + ) { + _err_handler = handler; + return H5PART_SUCCESS; +} + +h5part_error_handler +H5_get_errorhandler ( + void + ) { + return _err_handler; +} + +h5part_int64_t +H5_get_errno ( + void + ) { + return _h5part_errno; +} + + +/*! + \ingroup h5part_errhandle + + This is the H5Part default error handler. If an error occures, an + error message will be printed and an error number will be returned. + + \return value given in \c eno +*/ +h5part_int64_t +H5_report_errorhandler ( + const char *funcname, + const h5part_int64_t eno, + const char *fmt, + ... + ) { + + _h5part_errno = eno; + if ( _debug > 0 ) { + va_list ap; + va_start ( ap, fmt ); + H5_vprint_error ( fmt, ap ); + va_end ( ap ); + } + return _h5part_errno; +} + +/*! + \ingroup h5part_errhandle + + If an error occures, an error message will be printed and the + program exists with the error code given in \c eno. +*/ +h5part_int64_t +H5_abort_errorhandler ( + const char *funcname, + const h5part_int64_t eno, + const char *fmt, + ... + ) { + + _h5part_errno = eno; + if ( _debug > 0 ) { + va_list ap; + va_start ( ap, fmt ); + fprintf ( stderr, "%s: ", funcname ); + vfprintf ( stderr, fmt, ap ); + fprintf ( stderr, "\n" ); + } + exit (-(int)_h5part_errno); +} + +static void +_vprintf ( + FILE* f, + const char *prefix, + const char *fmt, + va_list ap + ) { + char *fmt2 = (char*)malloc( strlen ( prefix ) +strlen ( fmt ) + strlen ( __funcname ) + 16 ); + if ( fmt2 == NULL ) return; + sprintf ( fmt2, "%s: %s: %s\n", prefix, __funcname, fmt ); + vfprintf ( stderr, fmt2, ap ); + free ( fmt2 ); +} + +void +H5_vprint_error ( + const char *fmt, + va_list ap + ) { + + if ( _debug < 1 ) return; + _vprintf ( stderr, "E", fmt, ap ); +} + +void +H5_print_error ( + const char *fmt, + ... + ) { + + va_list ap; + va_start ( ap, fmt ); + H5_vprint_error ( fmt, ap ); + va_end ( ap ); +} + +void +H5_vprint_warn ( + const char *fmt, + va_list ap + ) { + + if ( _debug < 2 ) return; + _vprintf ( stderr, "W", fmt, ap ); +} + +void +H5_print_warn ( + const char *fmt, + ... + ) { + + va_list ap; + va_start ( ap, fmt ); + H5_vprint_warn ( fmt, ap ); + va_end ( ap ); +} + +void +H5_vprint_info ( + const char *fmt, + va_list ap + ) { + + if ( _debug < 3 ) return; + _vprintf ( stdout, "I", fmt, ap ); +} + +void +H5_print_info ( + const char *fmt, + ... + ) { + + va_list ap; + va_start ( ap, fmt ); + H5_vprint_info ( fmt, ap ); + va_end ( ap ); +} + +void +H5_vprint_debug ( + const char *fmt, + va_list ap + ) { + + if ( _debug < 4 ) return; + _vprintf ( stdout, "D", fmt, ap ); +} + +void +H5_print_debug ( + const char *fmt, + ... + ) { + + va_list ap; + va_start ( ap, fmt ); + H5_vprint_debug ( fmt, ap ); + va_end ( ap ); +} + +void +H5_set_funcname ( + char * const fname + ) { + __funcname = fname; +} + +const char * +H5_get_funcname ( + void + ) { + return __funcname; +} diff --git a/src/h5/errorhandling.h b/src/h5/errorhandling.h new file mode 100644 index 0000000..241fe6d --- /dev/null +++ b/src/h5/errorhandling.h @@ -0,0 +1,118 @@ +#ifndef __ERRORHANDLING_H +#define __ERRORHANDLING_H + +h5part_int64_t +H5_set_debuglevel ( + h5part_int64_t level + ); + +h5part_int64_t +H5_get_debuglevel ( + void + ); + +h5part_int64_t +H5_set_errorhandler ( + h5part_error_handler handler + ); + +h5part_error_handler +H5_get_errorhandler ( + void + ); + +h5part_int64_t +H5_get_errno ( + void + ); + +h5part_int64_t +H5_report_errorhandler ( + const char *funcname, + const h5part_int64_t eno, + const char *fmt, + ... + ); + +h5part_int64_t +H5_abort_errorhandler ( + const char *funcname, + const h5part_int64_t eno, + const char *fmt, + ... + ) ; + +void +H5_vprint_error ( + const char *fmt, + va_list ap + ); + +void +H5_print_error ( + const char *fmt, + ... ) +#ifdef __GNUC__ +__attribute__ ((format (printf, 1, 2))) +#endif +; + +void +H5_vprint_warn ( + const char *fmt, + va_list ap + ); + +void +H5_print_warn ( + const char *fmt, + ... + ) +#ifdef __GNUC__ +__attribute__ ((format (printf, 1, 2))) +#endif +; + +void +H5_vprint_info ( + const char *fmt, + va_list ap + ); + +void +H5_print_info ( + const char *fmt, + ... + ) +#ifdef __GNUC__ +__attribute__ ((format (printf, 1, 2))) +#endif +; + +void +H5_vprint_debug ( + const char *fmt, + va_list ap + ); + +void +H5_print_debug ( + const char *fmt, + ... + ) +#ifdef __GNUC__ +__attribute__ ((format (printf, 1, 2))) +#endif +; + +void +H5_set_funcname ( + char * const fname + ); + +const char * +H5_get_funcname ( + void + ); + +#endif diff --git a/src/h5/openclose.c b/src/h5/openclose.c new file mode 100644 index 0000000..686dc8f --- /dev/null +++ b/src/h5/openclose.c @@ -0,0 +1,436 @@ +#include +#include +#include /* va_arg - System dependent ?! */ +#include +#include +#include +#include + +#include "H5PartTypes.h" +#include "H5BlockTypes.h" +#include "H5Part.h" +#include "H5Block.h" +#include "H5PartPrivate.h" +#include "H5BlockPrivate.h" +#include "H5PartErrors.h" +#include "H5BlockErrors.h" +#include "H5.h" + +extern h5part_error_handler _err_handler; +extern h5part_int64_t _h5part_errno; +extern unsigned _debug; + +static h5part_int64_t +_close_block ( + H5PartFile *f + ); + +/*! + \ingroup h5block_private + + \internal + + Check whether \c f points to a valid file handle. + + \return H5PART_SUCCESS or error code +*/ +h5part_int64_t +H5_check_filehandle ( + const H5PartFile *f /*!< filehandle to check validity of */ + ) { + + if ( f == NULL ) + return HANDLE_H5PART_BADFD_ERR; + if ( f->file == 0 ) + return HANDLE_H5PART_BADFD_ERR; + if ( f->block == NULL ) + return HANDLE_H5PART_BADFD_ERR; + return H5PART_SUCCESS; +} + + +/*! + Initialize H5Part +*/ +static herr_t +_h5_error_handler ( void* unused ) { + + if ( _debug >= 5 ) { + H5Eprint (stderr); + } + return 0; +} + +static h5part_int64_t +_init ( void ) { + static int __init = 0; + + herr_t r5; + if ( ! __init ) { + r5 = H5Eset_auto ( _h5_error_handler, NULL ); + if ( r5 < 0 ) return H5PART_ERR_INIT; + } + __init = 1; + return H5PART_SUCCESS; +} + +/*! + \ingroup h5block_private + + \internal + + Initialize H5Block internal structure. + + \return H5PART_SUCCESS or error code +*/ +static h5part_int64_t +_init_block ( + H5PartFile *f /*!< IN: file handle */ + ) { + h5part_int64_t herr; + struct H5BlockStruct *b; + + herr = _file_is_valid ( f ); + if ( herr == H5PART_SUCCESS ) return H5PART_SUCCESS; + + if ( (f == 0) || (f->file == 0) ) return HANDLE_H5PART_BADFD_ERR; + + f->block = (struct H5BlockStruct*) malloc( sizeof (*f->block) ); + if ( f->block == NULL ) { + return HANDLE_H5PART_NOMEM_ERR; + } + b = f->block; + memset ( b, 0, sizeof (*b) ); + b->user_layout = (struct H5BlockPartition*) malloc ( + f->nprocs * sizeof (b->user_layout[0]) ); + if ( b->user_layout == NULL ) { + return HANDLE_H5PART_NOMEM_ERR; + } + b->write_layout = (struct H5BlockPartition*) malloc ( + f->nprocs * sizeof (b->write_layout[0]) ); + if ( b->write_layout == NULL ) { + return HANDLE_H5PART_NOMEM_ERR; + } + b->timestep = -1; + b->blockgroup = -1; + b->shape = -1; + b->diskshape = -1; + b->memshape = -1; + b->field_group_id = -1; + b->have_layout = 0; + + f->close_block = _close_block; + + return H5PART_SUCCESS; +} + +/*! + \ingroup h5block_private + + \internal + + De-initialize H5Block internal structure. Open HDF5 objects are + closed and allocated memory freed. + + \return H5PART_SUCCESS or error code +*/ +static h5part_int64_t +_close_block ( + H5PartFile *f /*!< IN: file handle */ + ) { + + herr_t herr; + struct H5BlockStruct *b = f->block; + + if ( b->blockgroup >= 0 ) { + herr = H5Gclose ( b->blockgroup ); + if ( herr < 0 ) return HANDLE_H5G_CLOSE_ERR; + b->blockgroup = -1; + } + if ( b->shape >= 0 ) { + herr = H5Sclose ( b->shape ); + if ( herr < 0 ) return HANDLE_H5S_CLOSE_ERR; + b->shape = -1; + } + if ( b->diskshape >= 0 ) { + herr = H5Sclose ( b->diskshape ); + if ( herr < 0 ) return HANDLE_H5S_CLOSE_ERR; + b->diskshape = -1; + } + if ( b->memshape >= 0 ) { + herr = H5Sclose ( b->memshape ); + if ( herr < 0 ) return HANDLE_H5S_CLOSE_ERR; + b->memshape = -1; + } + free ( f->block ); + f->block = NULL; + f->close_block = NULL; + + return H5PART_SUCCESS; +} + + +H5PartFile* +H5_open_file ( + const char *filename, /*!< [in] The name of the data file to open. */ + unsigned flags, /*!< [in] The access mode for the file. */ + MPI_Comm comm, /*!< [in] MPI communicator */ + int f_parallel /*!< [in] 0 for serial io otherwise parallel */ + ) { + + h5part_int64_t rc = H5PART_SUCCESS; + + if ( _init() < 0 ) { + HANDLE_H5PART_INIT_ERR; + return NULL; + } + _h5part_errno = H5PART_SUCCESS; + H5PartFile *f = NULL; + + f = (H5PartFile*) malloc( sizeof (H5PartFile) ); + if( f == NULL ) { + HANDLE_H5PART_NOMEM_ERR; + goto error_cleanup; + } + memset (f, 0, sizeof (H5PartFile)); + + f->groupname_step = strdup ( H5PART_GROUPNAME_STEP ); + if( f->groupname_step == NULL ) { + HANDLE_H5PART_NOMEM_ERR; + goto error_cleanup; + } + f->stepno_width = 0; + + f->xfer_prop = f->create_prop = f->access_prop = H5P_DEFAULT; + + if ( f_parallel ) { +#ifdef PARALLEL_IO + /* for the SP2... perhaps different for linux */ + MPI_Info info = MPI_INFO_NULL; + + /* ks: IBM_large_block_io */ + MPI_Info_create(&info); + MPI_Info_set(info, "IBM_largeblock_io", "true" ); + + if (MPI_Comm_size (comm, &f->nprocs) != MPI_SUCCESS) { + HANDLE_MPI_COMM_SIZE_ERR; + goto error_cleanup; + } + if (MPI_Comm_rank (comm, &f->myproc) != MPI_SUCCESS) { + HANDLE_MPI_COMM_RANK_ERR; + goto error_cleanup; + } + + f->pnparticles = + (h5part_int64_t*) malloc (f->nprocs * sizeof (h5part_int64_t)); + if (f->pnparticles == NULL) { + HANDLE_H5PART_NOMEM_ERR; + goto error_cleanup; + } + + f->access_prop = H5Pcreate (H5P_FILE_ACCESS); + if (f->access_prop < 0) { + HANDLE_H5P_CREATE_ERR; + goto error_cleanup; + } + + if (H5Pset_fapl_mpio (f->access_prop, comm, info) < 0) { + HANDLE_H5P_SET_FAPL_MPIO_ERR; + goto error_cleanup; + } + + /* f->create_prop = H5Pcreate(H5P_FILE_CREATE); */ + f->create_prop = H5P_DEFAULT; + + /* xfer_prop: also used for parallel I/O, during actual writes + rather than the access_prop which is for file creation. */ + f->xfer_prop = H5Pcreate (H5P_DATASET_XFER); + if (f->xfer_prop < 0) { + HANDLE_H5P_CREATE_ERR; + goto error_cleanup; + } + +#ifdef COLLECTIVE_IO + if (H5Pset_dxpl_mpio (f->xfer_prop,H5FD_MPIO_COLLECTIVE) < 0) { + HANDLE_H5P_SET_DXPL_MPIO_ERR; + goto error_cleanup; + } +#endif + f->comm = comm; + + MPI_Info_free(&info); +#else + /* f_parallel is true, but compilation is for serial I/O */ + HANDLE_MPI_UNAVAILABLE_ERR; + goto error_cleanup; + +#endif /* PARALLEL_IO */ + } else { + f->comm = 0; + f->nprocs = 1; + f->myproc = 0; + f->pnparticles = + (h5part_int64_t*) malloc (f->nprocs * sizeof (h5part_int64_t)); + } + if ( flags == H5PART_READ ) { + f->file = H5Fopen (filename, H5F_ACC_RDONLY, f->access_prop); + } + else if ( flags == H5PART_WRITE ){ + f->file = H5Fcreate (filename, H5F_ACC_TRUNC, f->create_prop, + f->access_prop); + f->empty = 1; + } + else if ( flags == H5PART_APPEND ) { + int fd = open (filename, O_RDONLY, 0); + if ( (fd == -1) && (errno == ENOENT) ) { + f->file = H5Fcreate(filename, H5F_ACC_TRUNC, + f->create_prop, f->access_prop); + f->empty = 1; + } + else if (fd != -1) { + close (fd); + f->file = H5Fopen (filename, H5F_ACC_RDWR, + f->access_prop); + /* + The following function call returns an error, + if f->file < 0. But we can safely ignore this. + */ + f->timestep = H5_get_num_objects_matching_pattern( + f->file, "/", H5G_GROUP, f->groupname_step ); + if ( f->timestep < 0 ) goto error_cleanup; + } + } + else { + HANDLE_H5PART_FILE_ACCESS_TYPE_ERR ( flags ); + goto error_cleanup; + } + + if (f->file < 0) { + HANDLE_H5F_OPEN_ERR ( filename, flags ); + goto error_cleanup; + } + f->root_id = H5Gopen( f->file, "/" ); + if ( f->root_id < 0 ) { + HANDLE_H5G_OPEN_ERR ( "/" ); + goto error_cleanup; + } + f->mode = flags; + f->timegroup = -1; + f->shape = 0; + f->diskshape = H5S_ALL; + f->memshape = H5S_ALL; + f->viewstart = -1; + f->viewend = -1; + + sprintf ( + f->index_name, + "%s#%0*lld", + f->groupname_step, f->stepno_width, (long long) f->timestep ); + + rc = _init_block ( f ); + if ( rc != H5PART_SUCCESS ) { + goto error_cleanup; + } + + H5_print_debug ( + "Proc[%d]: Opened file \"%s\" val=%lld", + f->myproc, + filename, + (long long)(size_t)f ); + + return f; + + error_cleanup: + if (f != NULL ) { + if (f->groupname_step) { + free (f->groupname_step); + } + if (f->pnparticles != NULL) { + free (f->pnparticles); + } + free (f); + } + return NULL; +} + + +h5part_int64_t +H5_close_file ( + H5PartFile *f + ) { + herr_t r = 0; + _h5part_errno = H5PART_SUCCESS; + + CHECK_FILEHANDLE ( f ); + + if ( f->block && f->close_block ) { + (*f->close_block) ( f ); + f->block = NULL; + f->close_block = NULL; + } + + if( f->shape > 0 ) { + r = H5Sclose( f->shape ); + if ( r < 0 ) HANDLE_H5S_CLOSE_ERR; + f->shape = 0; + } + if( f->timegroup >= 0 ) { + r = H5Gclose( f->timegroup ); + if ( r < 0 ) HANDLE_H5G_CLOSE_ERR; + f->timegroup = -1; + } + if( f->diskshape != H5S_ALL ) { + r = H5Sclose( f->diskshape ); + if ( r < 0 ) HANDLE_H5S_CLOSE_ERR; + f->diskshape = 0; + } + if( f->xfer_prop != H5P_DEFAULT ) { + r = H5Pclose( f->xfer_prop ); + if ( r < 0 ) HANDLE_H5P_CLOSE_ERR ( "f->xfer_prop" ); + f->xfer_prop = H5P_DEFAULT; + } + if( f->access_prop != H5P_DEFAULT ) { + r = H5Pclose( f->access_prop ); + if ( r < 0 ) HANDLE_H5P_CLOSE_ERR ( "f->access_prop" ); + f->access_prop = H5P_DEFAULT; + } + if( f->create_prop != H5P_DEFAULT ) { + r = H5Pclose( f->create_prop ); + if ( r < 0 ) HANDLE_H5P_CLOSE_ERR ( "f->create_prop" ); + f->create_prop = H5P_DEFAULT; + } + if ( f->root_id >= 0 ) { + r = H5Gclose ( f->root_id ); + if ( r < 0 ) HANDLE_H5G_CLOSE_ERR; + f->root_id = 0; + } + if ( f->file ) { + r = H5Fclose( f->file ); + if ( r < 0 ) HANDLE_H5F_CLOSE_ERR; + f->file = 0; + } + if (f->groupname_step) { + free (f->groupname_step); + } + if( f->pnparticles ) { + free( f->pnparticles ); + } + free( f ); + + return _h5part_errno; +} + +h5part_int64_t +H5_define_stepname ( + H5PartFile *f, + const char *name, + const h5part_int64_t width + ) { + f->groupname_step = strdup ( name ); + if( f->groupname_step == NULL ) { + return HANDLE_H5PART_NOMEM_ERR; + } + f->stepno_width = (int)width; + + return H5PART_SUCCESS; +} diff --git a/src/h5/openclose.h b/src/h5/openclose.h new file mode 100644 index 0000000..4259d00 --- /dev/null +++ b/src/h5/openclose.h @@ -0,0 +1,37 @@ +#ifndef __OPENCLOSE_H +#define __OPENCLOSE_H + +H5PartFile* +H5_open_file ( + const char *filename, + unsigned flags, + MPI_Comm comm, + int f_parallel + ); + +h5part_int64_t +H5_check_filehandle ( + const H5PartFile *f + ); + +H5PartFile* +H5_open_file ( + const char *filename, + unsigned flags, + MPI_Comm comm, + int f_parallel + ); + +h5part_int64_t +H5_close_file ( + H5PartFile *f + ); + +h5part_int64_t +H5_define_stepname ( + H5PartFile *f, + const char *name, + const h5part_int64_t width + ); + +#endif diff --git a/src/h5/readwrite.c b/src/h5/readwrite.c new file mode 100644 index 0000000..bf8c201 --- /dev/null +++ b/src/h5/readwrite.c @@ -0,0 +1,299 @@ +#include +#include +#include /* va_arg - System dependent ?! */ +#include +#include +#include +#include + +#include "H5PartTypes.h" +#include "H5BlockTypes.h" +#include "H5Part.h" +#include "H5Block.h" +#include "H5PartPrivate.h" +#include "H5BlockPrivate.h" +#include "H5PartErrors.h" +#include "H5BlockErrors.h" +#include "H5.h" + + +h5part_int64_t +H5_write_data ( + H5PartFile *f, /*!< IN: Handle to open file */ + const char *name, /*!< IN: Name to associate array with */ + const void *array, /*!< IN: Array to commit to disk */ + const hid_t type, /*!< IN: Type of data */ + const hid_t groupid, + const hid_t shape, + const hid_t memshape, + const hid_t diskshape + ) { + herr_t herr; + hid_t dataset_id; + + H5_print_debug ( "Create a dataset[%s] mounted on the " + "timestep %lld", + name, (long long)f->timestep ); + + dataset_id = H5Dcreate ( + groupid, + name, + type, + shape, + H5P_DEFAULT ); + if ( dataset_id < 0 ) + return HANDLE_H5D_CREATE_ERR ( name, f->timestep ); + + herr = H5Dwrite ( + dataset_id, + type, + memshape, + diskshape, + f->xfer_prop, + array ); + + if ( herr < 0 ) return HANDLE_H5D_WRITE_ERR ( name, f->timestep ); + + herr = H5Dclose ( dataset_id ); + if ( herr < 0 ) return HANDLE_H5D_CLOSE_ERR; + + f->empty = 0; + + return H5PART_SUCCESS; +} + + +/*! + \ingroup h5part_kernel + + Iterator for \c H5Giterate(). +*/ +herr_t +H5_iteration_operator ( + hid_t group_id, /*!< [in] group id */ + const char *member_name,/*!< [in] group name */ + void *operator_data /*!< [in,out] data passed to the iterator */ + ) { + + struct _iter_op_data *data = (struct _iter_op_data*)operator_data; + herr_t herr; + H5G_stat_t objinfo; + + if ( data->type != H5G_UNKNOWN ) { + herr = H5Gget_objinfo ( group_id, member_name, 1, &objinfo ); + if ( herr < 0 ) return (herr_t)HANDLE_H5G_GET_OBJINFO_ERR ( member_name ); + + if ( objinfo.type != data->type ) + return 0;/* don't count, continue iteration */ + } + + if ( data->name && (data->stop_idx == data->count) ) { + memset ( data->name, 0, data->len ); + strncpy ( data->name, member_name, data->len-1 ); + + return 1; /* stop iteration */ + } + /* + count only if pattern is NULL or member name matches + */ + if ( !data->pattern || + (strncmp (member_name, data->pattern, strlen(data->pattern)) == 0) + ) { + data->count++; + } + return 0; /* continue iteration */ +} + +/*! + \ingroup h5part_kernel + + Iterator for \c H5Giterate(). +*/ +h5part_int64_t +H5_get_num_objects ( + hid_t group_id, + const char *group_name, + const hid_t type + ) { + + return H5_get_num_objects_matching_pattern ( + group_id, + group_name, + type, + NULL ); +} + +/*! + \ingroup h5part_kernel + + Iterator for \c H5Giterate(). +*/ +h5part_int64_t +H5_get_num_objects_matching_pattern ( + hid_t group_id, + const char *group_name, + const hid_t type, + char * const pattern + ) { + + h5part_int64_t herr; + int idx = 0; + struct _iter_op_data data; + + memset ( &data, 0, sizeof ( data ) ); + data.type = type; + data.pattern = pattern; + + herr = H5Giterate ( group_id, group_name, &idx, + H5_iteration_operator, &data ); + if ( herr < 0 ) return herr; + + return data.count; +} + +/*! + \ingroup h5part_kernel + + Iterator for \c H5Giterate(). +*/ +h5part_int64_t +H5_get_object_name ( + hid_t group_id, + const char *group_name, + const hid_t type, + const h5part_int64_t idx, + char *obj_name, + const h5part_int64_t len_obj_name + ) { + + herr_t herr; + struct _iter_op_data data; + int iterator_idx = 0; + + memset ( &data, 0, sizeof ( data ) ); + data.stop_idx = (hid_t)idx; + data.type = type; + data.name = obj_name; + data.len = (size_t)len_obj_name; + + herr = H5Giterate ( group_id, group_name, &iterator_idx, + H5_iteration_operator, + &data ); + if ( herr < 0 ) return (h5part_int64_t)herr; + + if ( herr == 0 ) HANDLE_H5PART_NOENTRY_ERR( group_name, + type, idx ); + + return H5PART_SUCCESS; +} + +h5part_int64_t +H5_set_step ( + H5PartFile *f, /*!< [in] Handle to open file */ + const h5part_int64_t step /*!< [in] Time-step to set. */ + ) { + + sprintf ( + f->index_name, + "%s#%0*lld", + f->groupname_step, f->stepno_width, (long long) step ); + herr_t herr = H5Gget_objinfo( f->file, f->index_name, 1, NULL ); + if ( (f->mode != H5PART_READ) && ( herr >= 0 ) ) { + return HANDLE_H5PART_STEP_EXISTS_ERR ( step ); + } + + if ( f->timegroup >= 0 ) { + herr = H5Gclose ( f->timegroup ); + if ( herr < 0 ) return HANDLE_H5G_CLOSE_ERR; + } + f->timegroup = -1; + f->timestep = step; + + if( f->mode == H5PART_READ ) { + H5_print_info ( + "Proc[%d]: Set step to #%lld for file %lld", + f->myproc, + (long long)step, + (long long)(size_t) f ); + + f->timegroup = H5Gopen ( f->file, f->index_name ); + if ( f->timegroup < 0 ) return HANDLE_H5G_OPEN_ERR( f->index_name ); + } + else { + H5_print_debug ( + "Proc[%d]: Create step #%lld for file %lld", + f->myproc, + (long long)step, + (long long)(size_t) f ); + + f->timegroup = H5Gcreate ( f->file, f->index_name, 0 ); + if ( f->timegroup < 0 ) + return HANDLE_H5G_CREATE_ERR ( f->index_name ); + } + + return H5PART_SUCCESS; +} + +/*! + Normalize HDF5 type +*/ +hid_t +H5_normalize_h5_type ( + hid_t type + ) { + H5T_class_t tclass = H5Tget_class ( type ); + int size = H5Tget_size ( type ); + + switch ( tclass ){ + case H5T_INTEGER: + if ( size==8 ) { + return H5T_NATIVE_INT64; + } + else if ( size==1 ) { + return H5T_NATIVE_CHAR; + } + break; + case H5T_FLOAT: + return H5T_NATIVE_DOUBLE; + default: + ; /* NOP */ + } + H5_print_warn ( "Unknown type %d", (int)type ); + + return -1; +} + + +h5part_int64_t +H5_get_dataset_type( + hid_t group_id, + const char *dataset_name + ) { + hid_t dataset_id = H5Dopen ( group_id, dataset_name ); + if ( dataset_id < 0 ) HANDLE_H5D_OPEN_ERR ( dataset_name ); + + hid_t hdf5_type = H5Dget_type ( dataset_id ); + if ( hdf5_type < 0 ) HANDLE_H5D_GET_TYPE_ERR; + + h5part_int64_t type = (h5part_int64_t) H5_normalize_h5_type ( hdf5_type ); + + herr_t herr = H5Tclose(hdf5_type); + if ( herr < 0 ) HANDLE_H5T_CLOSE_ERR; + + herr = H5Dclose(dataset_id); + if ( herr < 0 ) HANDLE_H5D_CLOSE_ERR; + + return type; +} + +h5part_int64_t +H5_has_index ( + H5PartFile *f, /*!< [in] Handle to open file */ + h5part_int64_t step /*!< [in] Step number to query */ + ) { + char name[128]; + sprintf ( name, + "%s#%0*lld", + f->groupname_step, f->stepno_width, (long long) step ); + return ( H5Gget_objinfo( f->file, name, 1, NULL ) >= 0 ); +} diff --git a/src/h5/readwrite.h b/src/h5/readwrite.h new file mode 100644 index 0000000..d0ce157 --- /dev/null +++ b/src/h5/readwrite.h @@ -0,0 +1,64 @@ +#ifndef __READWRITE_H +#define __READWRITE_H + +h5part_int64_t +H5_write_data ( + H5PartFile *f, + const char *name, + const void *array, + const hid_t type, + const hid_t groupid, + const hid_t shape, + const hid_t memshape, + const hid_t diskshape + ) ; + +h5part_int64_t +H5_get_num_objects ( + hid_t group_id, + const char *group_name, + const hid_t type + ); + +h5part_int64_t +H5_get_num_objects_matching_pattern ( + hid_t group_id, + const char *group_name, + const hid_t type, + char * const pattern + ); + +h5part_int64_t +H5_get_object_name ( + hid_t group_id, + const char *group_name, + const hid_t type, + const h5part_int64_t idx, + char *obj_name, + const h5part_int64_t len_obj_name + ); + +h5part_int64_t +H5_set_step ( + H5PartFile *f, /*!< [in] Handle to open file */ + const h5part_int64_t step /*!< [in] Time-step to set. */ + ); + +hid_t +H5_normalize_h5_type ( + hid_t type + ); + +h5part_int64_t +H5_get_dataset_type( + hid_t group_id, + const char *dataset_name + ); + +h5part_int64_t +H5_has_index ( + H5PartFile *f, /*!< [in] Handle to open file */ + h5part_int64_t step /*!< [in] Step number to query */ + ); + +#endif diff --git a/src/h5/u_readwrite.c b/src/h5/u_readwrite.c new file mode 100644 index 0000000..b8ba745 --- /dev/null +++ b/src/h5/u_readwrite.c @@ -0,0 +1,563 @@ +#include +#include +#include /* va_arg - System dependent ?! */ +#include +#include +#include +#include + +#include "H5PartTypes.h" +#include "H5Part.h" +#include "H5PartPrivate.h" +#include "H5PartErrors.h" +#include "H5.h" + +extern h5part_error_handler _err_handler; +extern h5part_int64_t _h5part_errno; +extern unsigned _debug; + +static hid_t +_get_diskshape_for_reading ( + H5PartFile *f, + hid_t dataset + ) { + + herr_t r; + + hid_t space = H5Dget_space(dataset); + if ( space < 0 ) return (hid_t)HANDLE_H5D_GET_SPACE_ERR; + + if ( H5PartHasView(f) ){ + hsize_t stride; + hsize_t count; +#ifdef HDF5V160 + hssize_t start; +#else + hsize_t start; +#endif + + /* so, is this selection inclusive or exclusive? */ + start = f->viewstart; + count = f->viewend - f->viewstart; /* to be inclusive */ + stride=1; + + /* now we select a subset */ + if ( f->diskshape > 0 ) { + r = H5Sselect_hyperslab ( + f->diskshape, H5S_SELECT_SET, + &start, &stride, &count, NULL); + if ( r < 0 ) return (hid_t)HANDLE_H5S_SELECT_HYPERSLAB_ERR; + } + /* now we select a subset */ + r = H5Sselect_hyperslab ( + space,H5S_SELECT_SET, + &start, &stride, &count, NULL ); + if ( r < 0 ) return (hid_t)HANDLE_H5S_SELECT_HYPERSLAB_ERR; + + H5_print_debug ( + "Selection: range=%d:%d, npoints=%d s=%d", + (int)f->viewstart,(int)f->viewend, + (int)H5Sget_simple_extent_npoints(space), + (int)H5Sget_select_npoints(space) ); + } + return space; +} + +static hid_t +_get_memshape_for_reading ( + H5PartFile *f, + hid_t dataset + ) { + + if(H5PartHasView(f)) { + hsize_t dmax=H5S_UNLIMITED; + hsize_t len = f->viewend - f->viewstart; + hid_t r = H5Screate_simple(1,&len,&dmax); + if ( r < 0 ) return (hid_t)HANDLE_H5S_CREATE_SIMPLE_ERR ( len ); + return r; + } + else { + return H5S_ALL; + } +} + +h5part_int64_t +H5U_get_num_elems ( + H5PartFile *f /*!< [in] Handle to open file */ + ) { + + h5part_int64_t herr; + hid_t space_id; + hid_t dataset_id; + char dataset_name[128]; + char step_name[128]; + hsize_t nparticles; + + /* Get first dataset in current time-step */ + sprintf ( + step_name, + "%s#%0*lld", + f->groupname_step, f->stepno_width, (long long) f->timestep ); + + herr = H5_get_object_name ( + f->file, + step_name, + H5G_DATASET, + 0, + dataset_name, sizeof (dataset_name) ); + if ( herr < 0 ) return herr; + + dataset_id = H5Dopen ( f->timegroup, dataset_name ); + if ( dataset_id < 0 ) + return HANDLE_H5D_OPEN_ERR ( dataset_name ); + + space_id = _get_diskshape_for_reading ( f, dataset_id ); + if ( space_id < 0 ) return (h5part_int64_t)space_id; + + if ( H5PartHasView ( f ) ) { + nparticles = H5Sget_select_npoints ( space_id ); + if ( nparticles < 0 ) return HANDLE_H5S_GET_SELECT_NPOINTS_ERR; + } + else { + nparticles = H5Sget_simple_extent_npoints ( space_id ); + if ( nparticles < 0 ) + return HANDLE_H5S_GET_SIMPLE_EXTENT_NPOINTS_ERR; + } + if ( space_id != H5S_ALL ) { + herr = H5Sclose ( space_id ); + if ( herr < 0 ) return HANDLE_H5S_CLOSE_ERR; + } + herr = H5Dclose ( dataset_id ); + if ( herr < 0 ) return HANDLE_H5D_CLOSE_ERR; + + return (h5part_int64_t) nparticles; +} + +h5part_int64_t +H5U_read_elems ( + H5PartFile *f, /*!< [in] Handle to open file */ + const char *name, /*!< [in] Name to associate dataset with */ + void *array, /*!< [out] Array of data */ + const hid_t type + ) { + + herr_t herr; + hid_t dataset_id; + hid_t space_id; + hid_t memspace_id; + + if ( f->timegroup < 0 ) { + h5part_int64_t h5err = H5_set_step ( f, f->timestep ); + if ( h5err < 0 ) return h5err; + } + dataset_id = H5Dopen ( f->timegroup, name ); + if ( dataset_id < 0 ) return HANDLE_H5D_OPEN_ERR ( name ); + + space_id = _get_diskshape_for_reading ( f, dataset_id ); + if ( space_id < 0 ) return (h5part_int64_t)space_id; + + memspace_id = _get_memshape_for_reading ( f, dataset_id ); + if ( memspace_id < 0 ) return (h5part_int64_t)memspace_id; + +#ifdef INDEPENDENT_IO + herr = H5Dread ( + dataset_id, + type, + memspace_id, /* shape/size of data in memory (the + complement to disk hyperslab) */ + space_id, /* shape/size of data on disk + (get hyperslab if needed) */ + H5P_DEFAULT, /* ignore... its for parallel reads */ + array ); +#else + herr = H5Dread ( + dataset_id, + type, + memspace_id, /* shape/size of data in memory (the + complement to disk hyperslab) */ + space_id, /* shape/size of data on disk + (get hyperslab if needed) */ + f->xfer_prop, /* ignore... its for parallel reads */ + array ); +#endif + + if ( herr < 0 ) return HANDLE_H5D_READ_ERR ( name, f->timestep ); + + if ( space_id != H5S_ALL ) { + herr = H5Sclose (space_id ); + if ( herr < 0 ) return HANDLE_H5S_CLOSE_ERR; + } + + if ( memspace_id != H5S_ALL ) + herr = H5Sclose ( memspace_id ); + if ( herr < 0 ) return HANDLE_H5S_CLOSE_ERR; + + herr = H5Dclose ( dataset_id ); + if ( herr < 0 ) return HANDLE_H5D_CLOSE_ERR; + + return H5PART_SUCCESS; +} + +h5part_int64_t +H5U_set_num_elements ( + H5PartFile *f, /*!< [in] Handle to open file */ + h5part_int64_t nparticles /*!< [in] Number of particles */ + ) { + + CHECK_FILEHANDLE( f ); + + herr_t r = 0; + +#ifndef PARALLEL_IO + /* + if we are not using parallel-IO, there is enough information + to know that we can short circuit this routine. However, + for parallel IO, this is going to cause problems because + we don't know if things have changed globally + */ + if ( f->nparticles == nparticles ) { + return H5PART_SUCCESS; + } +#endif + if ( f->diskshape != H5S_ALL ) { + r = H5Sclose( f->diskshape ); + if ( r < 0 ) return HANDLE_H5S_CLOSE_ERR; + f->diskshape = H5S_ALL; + } + if(f->memshape != H5S_ALL) { + r = H5Sclose( f->memshape ); + if ( r < 0 ) return HANDLE_H5S_CLOSE_ERR; + f->memshape = H5S_ALL; + } + if( f->shape ) { + r = H5Sclose(f->shape); + if ( r < 0 ) return HANDLE_H5S_CLOSE_ERR; + } + f->nparticles =(hsize_t) nparticles; +#ifndef PARALLEL_IO + f->shape = H5Screate_simple (1, + &(f->nparticles), + NULL); + if ( f->shape < 0 ) HANDLE_H5S_CREATE_SIMPLE_ERR ( f->nparticles ); + +#else /* PARALLEL_IO */ + /* + The Gameplan here is to declare the overall size of the on-disk + data structure the same way we do for the serial case. But + then we must have additional "DataSpace" structures to define + our in-memory layout of our domain-decomposed portion of the particle + list as well as a "selection" of a subset of the on-disk + data layout that will be written in parallel to mutually exclusive + regions by all of the processors during a parallel I/O operation. + These are f->shape, f->memshape and f->diskshape respectively. + */ + + hsize_t start[1]; + + hsize_t stride[1]; + hsize_t count[1]; + hsize_t total; + hsize_t dmax = H5S_UNLIMITED; + register int i; + + /* + acquire the number of particles to be written from each MPI process + */ + + r = MPI_Allgather ( + &nparticles, 1, MPI_LONG_LONG, + f->pnparticles, 1, MPI_LONG_LONG, + f->comm); + if ( r != MPI_SUCCESS) { + return HANDLE_MPI_ALLGATHER_ERR; + } + if ( f->myproc == 0 ) { + _H5Part_print_debug ( "Particle offsets:" ); + for(i=0;inprocs;i++) + _H5Part_print_debug ( "\tnp=%lld", + (long long) f->pnparticles[i] ); + } + /* should I create a selection here? */ + + /* compute start offsets */ + stride[0] = 1; + start[0] = 0; + for (i=0; imyproc; i++) { + start[0] += f->pnparticles[i]; + } + + /* compute total nparticles */ + total = 0; + for (i=0; i < f->nprocs; i++) { + total += f->pnparticles[i]; + } + + /* declare overall datasize */ + f->shape = H5Screate_simple (1, &total, &total); + if (f->shape < 0) return HANDLE_H5S_CREATE_SIMPLE_ERR ( total ); + + + /* declare overall data size but then will select a subset */ + f->diskshape = H5Screate_simple (1, &total, &total); + if (f->diskshape < 0) return HANDLE_H5S_CREATE_SIMPLE_ERR ( total ); + + /* declare local memory datasize */ + f->memshape = H5Screate_simple (1, &(f->nparticles), &dmax); + if (f->memshape < 0) + return HANDLE_H5S_CREATE_SIMPLE_ERR ( f->nparticles ); + + count[0] = nparticles; + r = H5Sselect_hyperslab ( + f->diskshape, + H5S_SELECT_SET, + start, + stride, + count, NULL ); + if ( r < 0 ) return HANDLE_H5S_SELECT_HYPERSLAB_ERR; + + if ( f->timegroup < 0 ) { + r = H5_set_step ( f, 0 ); + if ( r < 0 ) return r; + + } +#endif + return H5PART_SUCCESS; +} + +h5part_int64_t +H5U_write_data ( + H5PartFile *f, /*!< IN: Handle to open file */ + const char *name, /*!< IN: Name to associate array with */ + const void *array, /*!< IN: Array to commit to disk */ + const hid_t type /*!< IN: Type of data */ + ) { + + CHECK_FILEHANDLE ( f ); + CHECK_WRITABLE_MODE( f ); + CHECK_TIMEGROUP( f ); + + return H5_write_data( + f, + name, + array, + type, + f->timegroup, + f->shape, + f->memshape, + f->diskshape ); +} + +h5part_int64_t +H5U_reset_view ( + H5PartFile *f + ) { + + herr_t herr = 0; + + f->viewstart = -1; + f->viewend = -1; + if ( f->shape != 0 ){ + herr = H5Sclose(f->shape); + if ( herr < 0 ) return HANDLE_H5S_CLOSE_ERR; + f->shape=0; + } + if(f->diskshape!=0 && f->diskshape!=H5S_ALL){ + herr = H5Sclose(f->diskshape); + if ( herr < 0 ) return HANDLE_H5S_CLOSE_ERR; + f->diskshape=H5S_ALL; + } + f->diskshape = H5S_ALL; + if(f->memshape!=0 && f->memshape!=H5S_ALL){ + herr = H5Sclose ( f->memshape ); + if ( herr < 0 ) return HANDLE_H5S_CLOSE_ERR; + f->memshape=H5S_ALL; + } + return H5PART_SUCCESS; +} + +h5part_int64_t +H5U_set_view ( + H5PartFile *f, /*!< [in] Handle to open file */ + h5part_int64_t start, /*!< [in] Start particle */ + h5part_int64_t end /*!< [in] End particle */ + ) { + h5part_int64_t herr = 0; + hsize_t total; + hsize_t stride = 1; + hsize_t dmax = H5S_UNLIMITED; + + H5_print_debug ( + "Set view (%lld,%lld).", + (long long)start,(long long)end); + + herr = H5U_reset_view ( f ); + if ( herr < 0 ) return herr; + + if ( start == -1 && end == -1 ) return H5PART_SUCCESS; + + /* + View has been reset so H5PartGetNumParticles will tell + us the total number of particles. + + For now, we interpret start=-1 to mean 0 and + end==-1 to mean end of file + */ + total = (hsize_t) H5U_get_num_elems ( f ); + if ( total < 0 ) return HANDLE_H5PART_GET_NUM_PARTICLES_ERR ( total ); + + if ( start == -1 ) start = 0; + if ( end == -1 ) end = total; + + H5_print_debug ( "Total nparticles=%lld", (long long)total ); + + /* so, is this selection inclusive or exclusive? + it appears to be inclusive for both ends of the range. + */ + if ( end < start ) { + H5_print_warn ( + "Nonfatal error. " + "End of view (%lld) is less than start (%lld).", + (long long)end, (long long)start ); + end = start; /* ensure that we don't have a range error */ + } + /* setting up the new view */ + f->viewstart = start; + f->viewend = end; + f->nparticles = end - start + 1; + + /* declare overall datasize */ + f->shape = H5Screate_simple ( 1, &total, &total ); + if ( f->shape < 0 ) + return HANDLE_H5S_CREATE_SIMPLE_ERR ( total ); + + /* declare overall data size but then will select a subset */ + f->diskshape= H5Screate_simple ( 1, &total, &total ); + if ( f->diskshape < 0 ) + return HANDLE_H5S_CREATE_SIMPLE_ERR ( total ); + + /* declare local memory datasize */ + f->memshape = H5Screate_simple(1,&(f->nparticles),&dmax); + if ( f->memshape < 0 ) + return HANDLE_H5S_CREATE_SIMPLE_ERR ( f->nparticles ); + + herr = H5Sselect_hyperslab ( + f->diskshape, + H5S_SELECT_SET, + (hsize_t*)&start, + &stride, + &total, + NULL ); + if ( herr < 0 ) return HANDLE_H5S_SELECT_HYPERSLAB_ERR; + + return H5PART_SUCCESS; +} + +h5part_int64_t +H5U_get_view ( + H5PartFile *f, + h5part_int64_t *start, + h5part_int64_t *end + ) { + + h5part_int64_t viewstart = 0; + h5part_int64_t viewend = 0; + + if ( f->viewstart >= 0 ) + viewstart = f->viewstart; + + if ( f->viewend >= 0 ) { + viewend = f->viewend; + } + else { + viewend = H5U_get_num_elems ( f ); + if ( viewend < 0 ) + return HANDLE_H5PART_GET_NUM_PARTICLES_ERR ( viewend ); + } + + if ( start ) *start = viewstart; + if ( end ) *end = viewend; + + return viewend - viewstart; +} + +h5part_int64_t +H5U_set_canonical_view ( + H5PartFile *f + ) { + h5part_int64_t herr = H5U_reset_view ( f ); + if ( herr < 0 ) return HANDLE_H5PART_SET_VIEW_ERR( herr, -1, -1 ); + +#ifdef PARALLEL_IO + h5part_int64_t start = 0; + h5part_int64_t end = 0; + h5part_int64_t n = 0; + int i = 0; + + n = H5U_get_num_elems ( f ); + if ( n < 0 ) return HANDLE_H5PART_GET_NUM_PARTICLES_ERR ( n ); + /* + now lets query the attributes for this group to see if there + is a 'pnparticles' group that contains the offsets for the + processors. + */ + if ( H5_read_attrib ( + f->timegroup, + "pnparticles", f->pnparticles ) < 0) { + /* + Attribute "pnparticles" is not available. So + subdivide the view into NP mostly equal pieces + */ + n /= f->nprocs; + for ( i=0; inprocs; i++ ) { + f->pnparticles[i] = n; + } + } + + for ( i = 0; i < f->myproc; i++ ){ + start += f->pnparticles[i]; + } + end = start + f->pnparticles[f->myproc] - 1; + herr = H5U_set_view ( f, start, end ); + if ( herr < 0 ) return HANDLE_H5PART_SET_VIEW_ERR ( herr, start, end ); + +#endif + + return H5PART_SUCCESS; +} + + +/*! + Get information about dataset in current index given by its index + */ +h5part_int64_t +H5U_get_dataset_info ( + H5PartFile *f, /*!< [in] Handle to open file */ + const h5part_int64_t idx,/*!< [in] Index of the dataset */ + char *dataset_name, /*!< [out] Name of dataset */ + const h5part_int64_t len_dataset_name, + /*!< [in] Size of buffer \c dataset_name */ + h5part_int64_t *type, /*!< [out] Type of data in dataset */ + h5part_int64_t *nelem /*!< [out] Number of elements. */ + ) { + + h5part_int64_t herr = H5_get_object_name ( + f->file, + f->index_name, + H5G_DATASET, + idx, + dataset_name, + len_dataset_name ); + if ( herr < 0 ) return herr; + + if ( nelem ) { + *nelem = H5U_get_num_elems ( f ); + if ( *nelem < 0 ) return *nelem; + } + + if ( type ) { + *type = H5_get_dataset_type( f->timegroup, dataset_name ); + if ( *type < 0 ) return *type; + } + + return H5PART_SUCCESS; +} diff --git a/src/h5/u_readwrite.h b/src/h5/u_readwrite.h new file mode 100644 index 0000000..dfb3142 --- /dev/null +++ b/src/h5/u_readwrite.h @@ -0,0 +1,64 @@ +#ifndef __U_READWRITE_H +#define __U_READWRITE_H + +h5part_int64_t +H5U_get_num_elems ( + H5PartFile *f + ); + +h5part_int64_t +H5U_read_elems ( + H5PartFile *f, + const char *name, + void *array, + const hid_t type + ); + +h5part_int64_t +H5U_set_num_elements ( + H5PartFile *f, + h5part_int64_t nparticles + ); + +h5part_int64_t +H5U_write_data ( + H5PartFile *f, + const char *name, + const void *array, + const hid_t type + ); + +h5part_int64_t +H5U_reset_view ( + H5PartFile *f + ); + +h5part_int64_t +H5U_set_view ( + H5PartFile *f, + h5part_int64_t start, + h5part_int64_t end + ); + +h5part_int64_t +H5U_get_view ( + H5PartFile *f, + h5part_int64_t *start, + h5part_int64_t *end + ); + +h5part_int64_t +H5U_set_canonical_view ( + H5PartFile *f + ); + +h5part_int64_t +H5U_get_dataset_info ( + H5PartFile *f, + const h5part_int64_t idx, + char *dataset_name, + const h5part_int64_t len_dataset_name, + h5part_int64_t *type, + h5part_int64_t *nelem + ); +#endif