From 06c8da20b126ed2947a36e48a065e67808f1f00e Mon Sep 17 00:00:00 2001 From: Albert Cheng Date: Mon, 30 Aug 1999 23:55:00 -0500 Subject: [svn-r1621] Added GASS driver. Coded by Saurabh Bagchi, bagchi@uiuc.edu. Minor changes done to test/gass_xxx.c so that they print the test skip message when GASS driver is not available. This change is the implementation of GASS within HDF5-1.3 (HDF5 with Virtual File Layer). The GASS driver gives the facility of accessing HDF files on remote ftp servers. To use the GASS driver, the option --with-gass= shoud be specified with configure. An example of the command line used to test the distribution was: ./configure --disable-shared --without-hdf4 --with-gass=/afs/ncsa/projects/hdf/v5/bagchi/globus/GLB/development/sparc-sun-solaris2.6_nothreads_standard_debug/include,/afs/ncsa/projects/hdf/v5/bagchi/globus/GLB/development/sparc-sun-solaris2.6_nothreads_standard_debug/lib --disable-parallel The user should change the path to point to his local GASS installation. Documentation about the features of GASS and the HDF-GASS design is available separately and till it is put up on the official web site, anyone interested may contact me. Test programs to read, write or append remote files have been provided in the test directory as "gass_read.c", "gass_write.c", "gass_append.c". The test programs have the ftp site to access #define-d at the top of the file which the user can change accordingly. ./src/H5Epublic. Added new error type for file close. ./src/H5F.c Added hooks for the GASS driver. ./src/H5public.h Added header files for GASS & Globus. ./src/Makefile.in Added dependancy on GASS driver in LIB_SRC. ./src/hdf5.h Included header file for GASS driver. ./src/H5FDgass.c [NEW] Routines for the GASS driver. ./src/H5FDgass.h [NEW] Header file for the GASS driver. ./test/Makefile.in Added dependancy on the gass test routines. ./test/gass_read.c File to test remote file reading using GASS. ./test/gass_write.c File to test remote file writing using GASS. ./test/gass_append.c File to test remote file appending using GASS. --- src/H5Epublic.h | 1 + src/H5F.c | 7 +- src/H5FD.c | 3 + src/H5FDgass.c | 648 +++++++++++++++++++++++++++++++++++++++++++++++++++++ src/H5FDgass.h | 48 ++++ src/H5public.h | 6 + src/Makefile.in | 2 +- src/hdf5.h | 1 + test/Makefile.in | 16 +- test/gass_append.c | 148 ++++++++++++ test/gass_read.c | 200 +++++++++++++++++ test/gass_write.c | 157 +++++++++++++ 12 files changed, 1233 insertions(+), 4 deletions(-) create mode 100644 src/H5FDgass.c create mode 100644 src/H5FDgass.h create mode 100644 test/gass_append.c create mode 100644 test/gass_read.c create mode 100644 test/gass_write.c diff --git a/src/H5Epublic.h b/src/H5Epublic.h index 7d835d2..07ba0f1 100644 --- a/src/H5Epublic.h +++ b/src/H5Epublic.h @@ -100,6 +100,7 @@ typedef enum H5E_minor_t { H5E_FILEOPEN, /*file already open */ H5E_CANTCREATE, /*Can't create file */ H5E_CANTOPENFILE, /*Can't open file */ + H5E_CANTCLOSEFILE, /*Can't close file */ H5E_NOTHDF5, /*not an HDF5 format file */ H5E_BADFILE, /*bad file ID accessed */ H5E_TRUNCATED, /*file has been truncated */ diff --git a/src/H5F.c b/src/H5F.c index ce48d6f..7d57120 100644 --- a/src/H5F.c +++ b/src/H5F.c @@ -11,7 +11,7 @@ * MODIFICATIONS * Robb Matzke, 30 Aug 1997 * Added `ERRORS' fields to function prologues. -* * +* ****************************************************************************/ #ifdef RCSID @@ -24,6 +24,7 @@ static char RcsId[] = "@(#)$Revision$"; #include /*temporary in-memory files */ #include /*family of files */ #include /*MPI-2 I/O */ +#include /*GASS I/O */ #include /*multiple files partitioned by mem usage */ #include /*Posix unbuffered I/O */ @@ -202,6 +203,9 @@ H5F_init_interface(void) H5E_BEGIN_TRY { if ((status=H5FD_SEC2)<0) goto end_registration; if ((status=H5FD_FAMILY)<0) goto end_registration; +#ifdef HAVE_GASS + if ((status=H5FD_GASS)<0) goto end_registration; +#endif if ((status=H5FD_CORE)<0) goto end_registration; if ((status=H5FD_MULTI)<0) goto end_registration; #ifdef HAVE_PARALLEL @@ -209,6 +213,7 @@ H5F_init_interface(void) #endif end_registration: ; } H5E_END_TRY; + if (status<0) { HRETURN_ERROR(H5E_FILE, H5E_CANTINIT, FAIL, "file driver registration failed"); diff --git a/src/H5FD.c b/src/H5FD.c index c025090..c060e86 100644 --- a/src/H5FD.c +++ b/src/H5FD.c @@ -163,14 +163,17 @@ H5FDregister(const H5FD_class_t *cls) HRETURN_ERROR(H5E_ARGS, H5E_UNINITIALIZED, FAIL, "null class pointer is disallowed"); } + if (!cls->open || !cls->close) { HRETURN_ERROR(H5E_ARGS, H5E_UNINITIALIZED, FAIL, "`open' and/or `close' methods are not defined"); } + if (!cls->get_eoa || !cls->set_eoa) { HRETURN_ERROR(H5E_ARGS, H5E_UNINITIALIZED, FAIL, "`get_eoa' and/or `set_eoa' methods are not defined"); } + if (!cls->get_eof) { HRETURN_ERROR(H5E_ARGS, H5E_UNINITIALIZED, FAIL, "`get_eof' method is not defined"); diff --git a/src/H5FDgass.c b/src/H5FDgass.c new file mode 100644 index 0000000..055e12f --- /dev/null +++ b/src/H5FDgass.c @@ -0,0 +1,648 @@ +/* + * Copyright © 1999 NCSA + * All rights reserved. + * + * Programmer: Saurabh Bagchi (bagchi@uiuc.edu) + * Thursday, August 12 -Tuesday, August 17, 1999 + * + * Purpose: This is the GASS I/O driver. + * + */ +#include +#include +#include +#include +#include +#include +#include + +/* Packages needed by this file.*/ +#include + +#undef MAX +#define MAX(X,Y) ((X)>(Y)?(X):(Y)) + +/* The driver identification number, initialized at runtime */ +static hid_t H5FD_GASS_g = 0; + +#ifdef HAVE_GASS + +/* File operations */ +#define OP_UNKNOWN 0 +#define OP_READ 1 +#define OP_WRITE 2 + +/* + * The description of a file belonging to this driver. The `eoa' and `eof' + * determine the amount of hdf5 address space in use and the high-water mark + * of the file (the current size of the underlying Unix file). The `pos' + * value is used to eliminate file position updates when they would be a + * no-op. Unfortunately we've found systems that use separate file position + * indicators for reading and writing so the lseek can only be eliminated if + * the current operation is the same as the previous operation. When opening + * a file the `eof' will be set to the current file size, `eoa' will be set + * to zero, `pos' will be set to H5F_ADDR_UNDEF (as it is when an error + * occurs), and `op' will be set to H5F_OP_UNKNOWN. + */ +typedef struct H5FD_gass_t { + H5FD_t pub; /*public stuff, must be first */ + int fd; /*the unix file */ + GASS_Info info; /*file information */ + haddr_t eoa; /*end of allocated region */ + haddr_t eof; /*end of file; current file size*/ + haddr_t pos; /*current file I/O position */ + int op; /*last operation */ + + +} H5FD_gass_t; + +/* + * This driver supports systems that have the lseek64() function by defining + * some macros here so we don't have to have conditional compilations later + * throughout the code. + * + * file_offset_t: The datatype for file offsets, the second argument of + * the lseek() or lseek64() call. + * + * file_seek: The function which adjusts the current file position, + * either lseek() or lseek64(). + */ +#ifdef HAVE_LSEEK64 +# define file_offset_t off64_t +# define file_seek lseek64 +#else +# define file_offset_t off_t +# define file_seek lseek +#endif + +/* + * These macros check for overflow of various quantities. These macros + * assume that file_offset_t is signed and haddr_t and size_t are unsigned. + * + * ADDR_OVERFLOW: Checks whether a file address of type `haddr_t' + * is too large to be represented by the second argument + * of the file seek function. + * + * SIZE_OVERFLOW: Checks whether a buffer size of type `hsize_t' is too + * large to be represented by the `size_t' type. + * + * REGION_OVERFLOW: Checks whether an address and size pair describe data + * which can be addressed entirely by the second + * argument of the file seek function. + */ +#define MAXADDR (((haddr_t)1<<(8*sizeof(file_offset_t)-1))-1) +#define ADDR_OVERFLOW(A) (HADDR_UNDEF==(A) || \ + ((A) & ~(haddr_t)MAXADDR)) +#define SIZE_OVERFLOW(Z) ((Z) & ~(hsize_t)MAXADDR) +#define REGION_OVERFLOW(A,Z) (ADDR_OVERFLOW(A) || SIZE_OVERFLOW(Z) || \ + sizeof(file_offset_t)info; + return 0; +} + + +/*------------------------------------------------------------------------- + * Function: H5FD_gass_open + * + * Purpose: Opens a file with name NAME. The FLAGS are a bit field with + * purpose similar to the second argument of open(2) and which + * are defined in H5Fpublic.h. The file access property list + * FAPL_ID contains the driver properties and MAXADDR + * is the largest address which this file will be expected to + * access. + * + * Return: Success: A pointer to a new file data structure. The + * public fields will be initialized by the + * caller, which is always H5FD_open(). + * + * Failure: NULL + * + * Programmer: Saurabh Bagchi + * Friday, August 13, 1999 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static H5FD_t * +H5FD_gass_open(const char *name, unsigned flags, hid_t fapl_id, + haddr_t maxaddr) +{ + int fd; + struct stat sb; + H5FD_gass_t *file=NULL; + const H5FD_gass_fapl_t *fa=NULL; + H5FD_gass_fapl_t _fa; + char *filename = (char *) malloc(80 * sizeof(char)); + + /* fprintf(stdout, "Entering H5FD_gass_open name=%s flags=0x%x\n", name, flags); */ + + strcpy (filename, name); + + /* Obtain a pointer to gass-specific file access properties */ + if (H5P_DEFAULT==fapl_id || H5FD_GASS!=H5Pget_driver(fapl_id)) { + GASS_INFO_NULL (_fa.info); + /* _fa.info = GASS_INFO_NULL; */ + /* _fa.info = {0,0}; */ /*default*/ + fa = &_fa; + } else { + fa = H5Pget_driver_info(fapl_id); + assert(fa); + } + + /* Check arguments */ + if (!name || !*name) return NULL; + if (0==maxaddr || HADDR_UNDEF==maxaddr) return NULL; + if (ADDR_OVERFLOW(maxaddr)) return NULL; + + /* When I come down here, the possible flag values and the correct + responses are given here :- + + 1. H5F_ACC_CREAT | H5F_ACC_RDWR | H5F_ACC_EXCL : The file is + a new one. Go ahead and open it in O_RDWR. + + 2. H5F_ACC_CREAT | H5F_ACC_RDWR | H5F_ACC_TRUNC : Use + O_RDWR | O_TRUNC with gass_open. + + 3. H5F_ACC_RDWR | H5F_ACC_TRUNC : File already exists. Truncate it. + + 4. H5F_ACC_RDWR : Use O_RDWR with gass_open + + 5. H5F_ACC_RDWR is not set : Use O_RDONLY with gass_open + + One reason why we cannot simply pass on the flags to gass_open + is that gass_open does not support many of them (e.g., O_CREAT) + */ + + /* fprintf (stderr, "flags=0x%x\n", flags); */ + + if ((flags & H5F_ACC_CREAT) && (flags & H5F_ACC_RDWR) && (flags & H5F_ACC_EXCL)) { + if ((fd = globus_gass_open (filename, O_RDWR|O_TRUNC)) < 0) { + /* HRETURN_ERROR(H5E_IO, H5E_CANTOPENFILE, FAIL, "open failed"); */ + fprintf (stderr, "Can't open file. \n"); + return NULL; + } + + } + else if ((flags & H5F_ACC_CREAT) && (flags & H5F_ACC_RDWR) && (flags & H5F_ACC_TRUNC)) { + if ((fd = globus_gass_open (filename, O_RDWR|O_TRUNC)) < 0) { + /* HRETURN_ERROR(H5E_IO, H5E_CANTOPENFILE, NULL, "open failed"); */ + fprintf (stderr, "Can't open file. \n"); + return NULL; + } + + } + else if ((flags & H5F_ACC_RDWR) && (flags & H5F_ACC_TRUNC)) { + if ((fd = globus_gass_open (filename, O_RDWR|O_TRUNC)) < 0) { + /* HRETURN_ERROR(H5E_IO, H5E_CANTOPENFILE, NULL, "open failed"); */ + fprintf (stderr, "Can't open file. \n"); + return NULL; + } + + } + else if (flags & H5F_ACC_RDWR) { + printf ("I'm here in H5FDgass_open going to call globus_gass_open with O_RDWR. \n"); + printf ("Name of URL =%s \n", filename); + if ((fd = globus_gass_open (filename, O_RDWR)) < 0) { + /* HRETURN_ERROR(H5E_IO, H5E_CANTOPENFILE, NULL, "open failed"); */ + fprintf (stderr, "Can't open file. \n"); + return NULL; + } + + } + else { /* This is case where H5F_ACC_RDWR is not set */ + if ((fd = globus_gass_open (filename, O_RDONLY)) < 0) { + /* HRETURN_ERROR(H5E_IO, H5E_CANTOPENFILE, NULL, "open failed");*/ + fprintf (stderr, "Can't open file. \n"); + return NULL; + } + + } + + if (fstat(fd, &sb)<0) { + close(fd); + return NULL; + } + + /* Create the new file struct */ + file = calloc(1, sizeof(H5FD_gass_t)); + file->fd = fd; + file->eof = sb.st_size; + file->pos = HADDR_UNDEF; + file->op = OP_UNKNOWN; + file->info = fa->info; + + return (H5FD_t*)file; +} + +/*------------------------------------------------------------------------- + * Function: H5FD_gass_close + * + * Purpose: Closes a GASS file. + * + * Return: Success: 0 + * + * Failure: -1, file not closed. + * + * Programmer: Saurabh Bagchi + * Monday, August 16, 1999 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static herr_t +H5FD_gass_close (H5FD_t *_file) +{ + int gasserr; + H5FD_gass_t *file = (H5FD_gass_t *)_file; + + if (file == NULL) { + /* HRETURN_ERROR(H5E_IO, H5E_CANTCLOSEFILE, NULL, "close failed"); */ + fprintf (stderr, "Can't close file. \n"); + return -1; + } + + gasserr = globus_gass_close (file->fd); + if (gasserr == -1) + fprintf (stderr, "GASS close failed. \n"); + + return gasserr; +} + + +/*------------------------------------------------------------------------- + * Function: H5FD_gass_get_eoa + * + * Purpose: Gets the end-of-address marker for the file. The EOA marker + * is the first address past the last byte allocated in the + * format address space. + * + * Return: Success: The end-of-address marker. + * + * Failure: HADDR_UNDEF + * + * Programmer: Saurabh Bagchi + * Monday, August 16, 1999 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static haddr_t +H5FD_gass_get_eoa(H5FD_t *_file) +{ + H5FD_gass_t *file = (H5FD_gass_t *)_file; + return file->eoa; +} + + +/*------------------------------------------------------------------------- + * Function: H5FD_gass_set_eoa + * + * Purpose: Set the end-of-address marker for the file. This function is + * called shortly after an existing HDF5 file is opened in order + * to tell the driver where the end of the HDF5 data is located. + * + * Return: Success: 0 + * + * Programmer: Saurabh Bagchi + * Monday, August 16, 1999 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static herr_t +H5FD_gass_set_eoa(H5FD_t *_file, haddr_t addr) +{ + H5FD_gass_t *file = (H5FD_gass_t *)_file; + file->eoa = addr; + return 0; +} + + +/*------------------------------------------------------------------------- + * Function: H5FD_gass_get_eof + * + * Purpose: Returns the end-of-file marker, which is the greater of + * either the Unix end-of-file or the HDF5 end-of-address + * markers. + * + * Return: Success: End of file address, the first address past + * the end of the "file", either the Unix file + * or the HDF5 file. + * + * Failure: HADDR_UNDEF + * + * Programmer: Saurabh Bagchi + * Monday, August 16, 1999 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static haddr_t +H5FD_gass_get_eof(H5FD_t *_file) +{ + H5FD_gass_t *file = (H5FD_gass_t*)_file; + return MAX(file->eof, file->eoa); +} + +/*------------------------------------------------------------------------- + * Function: H5FD_gass_read + * + * Purpose: Reads SIZE bytes of data from FILE beginning at address ADDR + * into buffer BUF. + * + * Return: Success: Zero. Result is stored in caller-supplied + * buffer BUF. + * + * Failure: -1, Contents of buffer BUF are undefined. + * + * Programmer: Saurabh Bagchi + * Monday, August 16, 1999 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static herr_t +H5FD_gass_read(H5FD_t *_file, hid_t dxpl_id/*unused*/, haddr_t addr, + hsize_t size, void *buf/*out*/) +{ + H5FD_gass_t *file = (H5FD_gass_t*)_file; + ssize_t nbytes; + + assert(file && file->pub.cls); + assert(buf); + + /* Check for overflow conditions */ + if (HADDR_UNDEF==addr) return -1; + if (REGION_OVERFLOW(addr, size)) return -1; + if (addr+size>file->eoa) return -1; + + /* Seek to the correct location */ + if ((addr!=file->pos || OP_READ!=file->op) && + file_seek(file->fd, (file_offset_t)addr, SEEK_SET)<0) { + file->pos = HADDR_UNDEF; + file->op = OP_UNKNOWN; + return -1; + } + + /* + * Read data, being careful of interrupted system calls, partial results, + * and the end of the file. + */ + while (size>0) { +do nbytes = read(file->fd, buf, size); + while (-1==nbytes && EINTR==errno); + if (-1==nbytes) { + /* error */ + file->pos = HADDR_UNDEF; + file->op = OP_UNKNOWN; + return -1; + } + if (0==nbytes) { + /* end of file but not end of format address space */ + memset(buf, 0, size); + size = 0; + } + assert(nbytes>=0); + assert((hsize_t)nbytes<=size); + size -= (hsize_t)nbytes; + addr += (haddr_t)nbytes; + buf = (char*)buf + nbytes; + } + + /* Update current position */ + file->pos = addr; + file->op = OP_READ; + return 0; +} + +/*------------------------------------------------------------------------- + * Function: H5FD_gass_write + * + * Purpose: Writes SIZE bytes of data to FILE beginning at address ADDR + * from buffer BUF. + * + * Return: Success: Zero + * + * Failure: -1 + * + * Programmer: Saurabh Bagchi + * Tuesday, August 17, 1999 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static herr_t +H5FD_gass_write(H5FD_t *_file, hid_t dxpl_id/*unused*/, haddr_t addr, + hsize_t size, const void *buf) +{ + H5FD_gass_t *file = (H5FD_gass_t*)_file; + ssize_t nbytes; + + assert(file && file->pub.cls); + assert(buf); + + /* Check for overflow conditions */ + if (HADDR_UNDEF==addr) return -1; + if (REGION_OVERFLOW(addr, size)) return -1; + if (addr+size>file->eoa) return -1; + + /* Seek to the correct location */ + if ((addr!=file->pos || OP_WRITE!=file->op) && + file_seek(file->fd, (file_offset_t)addr, SEEK_SET)<0) { + file->pos = HADDR_UNDEF; + file->op = OP_UNKNOWN; + return -1; + } + + /* + * Write the data, being careful of interrupted system calls and partial + * results + */ + while (size>0) { + do nbytes = write(file->fd, buf, size); + while (-1==nbytes && EINTR==errno); +if (-1==nbytes) { + /* error */ + file->pos = HADDR_UNDEF; + file->op = OP_UNKNOWN; + return -1; + } + assert(nbytes>0); + assert((hsize_t)nbytes<=size); + size -= (hsize_t)nbytes; + addr += (haddr_t)nbytes; + buf = (const char*)buf + nbytes; + } + + /* Update current position and eof */ + file->pos = addr; + file->op = OP_WRITE; + if (file->pos>file->eof) file->eof = file->pos; + + return 0; +} + +#endif diff --git a/src/H5FDgass.h b/src/H5FDgass.h new file mode 100644 index 0000000..94cabbd --- /dev/null +++ b/src/H5FDgass.h @@ -0,0 +1,48 @@ +/* + * Copyright © 1999 NCSA + * All rights reserved. + * + * Programmer: Saurabh Bagchi + * Tuesday, August 17, 1999 + * + * Purpose: The public header file for the gass driver. + */ +#ifndef H5FDgass_H +#define H5FDgass_H + +#include +#include +#include + +#include + +#ifdef HAVE_GASS +#define H5FD_GASS (H5FD_gass_init()) +#else +#define H5FD_GASS (-1) +#endif + +#ifdef HAVE_GASS +/* Define the GASS info object. (Will be added to later as more GASS + functionality is sought to be exposed. */ +typedef struct GASS_Info { + unsigned long block_size; + unsigned long max_length; +} GASS_Info; + +#define GASS_INFO_NULL(v) memset((void *)&v, 0, sizeof(GASS_Info)); +/* + GASS_Info zzGassInfo = {0L,0L}; + #define GASS_INFO_NULL zzGassInfo +*/ +#endif + +/* Function prototypes */ +#ifdef HAVE_GASS +hid_t H5FD_gass_init(void); +herr_t H5Pset_fapl_gass(hid_t fapl_id, GASS_Info info); +herr_t H5Pget_fapl_gass(hid_t fapl_id, GASS_Info *info/*out*/); + +#endif + +#endif // H5FDgass_H diff --git a/src/H5public.h b/src/H5public.h index d2ef7ec..0a0321b 100644 --- a/src/H5public.h +++ b/src/H5public.h @@ -38,6 +38,12 @@ static char RcsId[] = "@(#)$Revision$"; # include #endif #endif + +#ifdef HAVE_GASS +#include "globus_common.h" +#include "globus_gass_file.h" +#endif + #include /* Version numbers */ diff --git a/src/Makefile.in b/src/Makefile.in index 2c3be81..5368802 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -22,7 +22,7 @@ CLEAN=libhdf5.settings ## Source and object files for the library (lexicographically)... LIB_SRC=H5.c H5A.c H5AC.c H5B.c H5D.c H5E.c H5F.c H5Farray.c H5Fistore.c \ - H5FD.c H5FDsec2.c H5FDfamily.c H5FDmpio.c H5FDcore.c H5FDmulti.c H5G.c \ + H5FD.c H5FDsec2.c H5FDfamily.c H5FDmpio.c H5FDcore.c H5FDmulti.c H5FDgass.c H5G.c \ H5Gent.c H5Gnode.c H5Gstab.c H5HG.c H5HL.c H5I.c H5MF.c H5MM.c H5O.c \ H5Oattr.c H5Ocomp.c H5Ocont.c H5Odtype.c H5Oefl.c H5Ofill.c H5Olayout.c \ H5Omtime.c H5Oname.c H5Onull.c H5Osdspace.c H5Oshared.c H5Ostab.c H5P.c \ diff --git a/src/hdf5.h b/src/hdf5.h index f5560fd..8add04a 100644 --- a/src/hdf5.h +++ b/src/hdf5.h @@ -44,6 +44,7 @@ #include /* File families */ #include /* Parallel files using MPI-2 I/O */ #include /* POSIX unbuffered file I/O */ +#include /* Remote files using GASS I/O */ #include /* Usage-partitioned file family */ #endif diff --git a/test/Makefile.in b/test/Makefile.in index 2e602a4..f438e6a 100644 --- a/test/Makefile.in +++ b/test/Makefile.in @@ -20,7 +20,7 @@ CPPFLAGS=-I. -I$(srcdir) -I../src -I$(top_srcdir)/src @CPPFLAGS@ RUNTEST=$(LT_RUN) TEST_PROGS=testhdf5 lheap ohdr stab gheap hyperslab istore bittests dtypes \ dsets cmpd_dset extend external links unlink big mtime fillval mount \ - flush1 flush2 enum + flush1 flush2 enum gass_write gass_read gass_append TIMINGS=iopipe chunk ragged overhead ## The libh5test.a library provides common support code for the tests. We link @@ -58,7 +58,9 @@ TEST_SRC=big.c bittests.c chunk.c cmpd_dset.c dsets.c dtypes.c extend.c \ external.c fillval.c flush1.c flush2.c gheap.c h5test.c hyperslab.c \ iopipe.c istore.c lheap.c links.c mount.c mtime.c ohdr.c overhead.c \ ragged.c stab.c tattr.c testhdf5.c tfile.c th5s.c tmeta.c trefer.c \ - tselect.c tvltypes.c unlink.c enum.c + tselect.c tvltypes.c unlink.c enum.c gass_write.c gass_read.c \ + gass_append.c + TEST_OBJ=$(TEST_SRC:.c=.lo) ## Private header files (not to be installed)... @@ -155,4 +157,14 @@ flush2: flush2.lo enum: enum.lo @$(LT_LINK_EXE) $(CFLAGS) -o $@ enum.lo $(LIB) $(LIBHDF5) $(LDFLAGS) $(LIBS) +gass_write: gass_write.lo + @$(LT_LINK_EXE) $(CFLAGS) -o $@ gass_write.lo $(LIB) $(LIBHDF5) $(LDFLAGS) $(LIBS) + +gass_read: gass_read.lo + @$(LT_LINK_EXE) $(CFLAGS) -o $@ gass_read.lo $(LIB) $(LIBHDF5) $(LDFLAGS) $(LIBS) + +gass_append: gass_append.lo + @$(LT_LINK_EXE) $(CFLAGS) -o $@ gass_append.lo $(LIB) $(LIBHDF5) $(LDFLAGS) $(LIBS) + @CONCLUDE@ + diff --git a/test/gass_append.c b/test/gass_append.c new file mode 100644 index 0000000..0764a39 --- /dev/null +++ b/test/gass_append.c @@ -0,0 +1,148 @@ +/* + * Copyright © 1998 NCSA + * All rights reserved. + * + * Programmer: Saurabh Bagchi (bagchi@uiuc.edu) + * Wednesday, August 11, 1999. + * + * Modifications: Saurabh Bagchi (Aug 17, 1999) + * Modified to work with VFL (HDF51.3). + */ + +/* Test the following functionality of the GASS driver. + 1. Open a remote file for append. + 2. Create a new dataset within the file. + 3. Create a local memory buffer to hold the data. + 4. Write the local data to the remote dataset. +*/ +#include + +#ifndef HAVE_GASS +int main(void) +{ + printf("Test skipped because GASS driver not available\n"); + return 0; +} +#else + +#define URL "ftp://bagchi:bagchi12@hdfspare1/scratch-fuga/home/bagchi/junk.w" +#define DATASETNAME "Int1Array" +#define NX 5 /* dataset dimensions */ +#define NY 6 +#define RANK 2 + +int main (void) +{ + + hid_t fapl =-1, file; + hid_t dataspace, datatype, dataset; + hsize_t dimsf[2]; + + herr_t status = 0; + int data[NX][NY]; /* data to write */ + int i, j; + GASS_Info ginf; + + /* + * Data and output buffer initialization. + */ + for (j = 0; j < NX; j++) { + for (i = 0; i < NY; i++) + data[j][i] = i*i + j*j; + } + /* + * 0 1 4 9 16 25 + * 1 2 5 10 17 26 + * 4 5 8 13 20 29 + * 9 10 13 18 25 34 + * 16 17 20 25 32 41 + */ + + /* Create access property list and set the driver to GASS */ + fapl = H5Pcreate (H5P_FILE_ACCESS); + if (fapl < 0) { + printf (" H5Pcreate failed. \n"); + return -1; + } + + ginf.block_size = 0; + ginf.max_length =0; + /* ginf = GASS_INFO_NULL; */ + + status = H5Pset_fapl_gass (fapl, ginf); + if (status < 0) { + printf ("H5Pset_fapl_gass failed. \n"); + return -1; + } + + /* + * Open an existing file using H5F_ACC_RDWR access, + * and gass file access properties. + */ + file = H5Fopen(URL, H5F_ACC_RDWR, fapl); + if (file < 0) { + printf ("H5Fopen failed. \n"); + return -1; + } + + /* + * Describe the size of the array and create the data space for fixed + * size dataset. + */ + dimsf[0] = NX; + dimsf[1] = NY; + dataspace = H5Screate_simple(RANK, dimsf, NULL); + if (dataspace < 0) { + printf ("H5Screate failed. \n"); + return -1; + } + + /* + * Define datatype for the data in the file. + * We will store little endian INT numbers. + */ + datatype = H5Tcopy(H5T_NATIVE_INT); + if (datatype < 0) { + printf ("H5Tcopy failed. \n"); + return -1; + } + + status = H5Tset_order(datatype, H5T_ORDER_LE); + if (status < 0) { + printf ("H5Tset_order failed. \n"); + return -1; + } + + /* + * Create a new dataset within the file using defined dataspace and + * datatype and default dataset creation properties. + */ + dataset = H5Dcreate(file, DATASETNAME, datatype, dataspace, + H5P_DEFAULT); + if (dataset < 0) { + printf ("H5Dcreate failed. \n"); + return -1; + } + + /* + * Write the data to the dataset using default transfer properties. + */ + status = H5Dwrite(dataset, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, + H5P_DEFAULT, data); + if (status < 0) { + printf ("H5Dwrite failed. \n"); + return -1; + } + + /* + * Close/release resources. + */ + H5Sclose(dataspace); + H5Tclose(datatype); + H5Dclose(dataset); + H5Fclose(file); + H5Pclose(fapl); + + return 0; +} +#endif diff --git a/test/gass_read.c b/test/gass_read.c new file mode 100644 index 0000000..f43cd02 --- /dev/null +++ b/test/gass_read.c @@ -0,0 +1,200 @@ +/* + * Copyright © 1998 NCSA + * All rights reserved. + * + * Programmer: Saurabh Bagchi (bagchi@uiuc.edu) + * Wednesday, August 11, 1999. + * + * Modifications: Saurabh Bagchi (Aug 17, 1999) + * Modified to work with VFL (HDF51.3). + */ + +/* Test the following functionality of the GASS driver. + 1. Open a remote file for read (the dataset was written using gass_write.c). + 2. Create a memory buffer to hold the dataset. + 3. Read the dataset into the memory buffer. + 4. Get some information about the dataset from the file. +*/ +#include +#include + +#ifndef HAVE_GASS +int main(void) +{ + printf("Test skipped because GASS driver not available\n"); + return 0; +} +#else + +#define URL "ftp://bagchi:bagchi12@hdfspare1/scratch-fuga/home/bagchi/junk.w" + +/* #define DATASETNAME "Int1Array" */ +#define NX_SUB 3 /* hyperslab dimensions */ +#define NY_SUB 4 +#define NX 7 /* output buffer dimensions */ +#define NY 7 +#define NZ 3 +#define RANK 2 +#define RANK_OUT 3 + +int +main (int argc, char **argv) +{ + hid_t fapl = -1, file, dataset; /* handles */ + char DATASETNAME[32]; + hid_t datatype, dataspace; + hid_t memspace; + H5T_class_t class; /* data type class */ + H5T_order_t order; /* data order */ + size_t size; /* + * size of the data element + * stored in file + */ + hsize_t dimsm[3]; /* memory space dimensions */ + hsize_t dims_out[2]; /* dataset dimensions */ + herr_t status; + + int data_out[NX][NY][NZ ]; /* output buffer */ + + hsize_t count[2]; /* size of the hyperslab in the file */ + hssize_t offset[2]; /* hyperslab offset in the file */ + hsize_t count_out[3]; /* size of the hyperslab in memory */ + hssize_t offset_out[3]; /* hyperslab offset in memory */ + int i, j, k, status_n, rank; + GASS_Info ginf; + + if (argc > 2) { + printf ("Incorrect command line. \n"); + printf ("Correct command line: %s [DATASET NAME] \n", argv[0]); + printf ("The two datasets present in the file are: \"IntArray\" and " + "\"Int1Array\"\n"); + exit(1); + } + + printf ("Correct command line: %s [DATASET NAME] \n", argv[0]); + printf ("The two datasets present in the file are: \"IntArray\" and " + "\"Int1Array\"\n"); + printf ("Default dataset is IntArray. \n"); + + if (argc == 1) + strcpy (DATASETNAME, "IntArray"); + else if (!strcmp(argv[1],"IntArray") || !strcmp(argv[1],"Int1Array")) + strcpy (DATASETNAME, argv[1]); + else + strcpy (DATASETNAME, "IntArray"); + printf ("\n Reading dataset %s \n\n", DATASETNAME); + + for (j = 0; j < NX; j++) { + for (i = 0; i < NY; i++) { + for (k = 0; k < NZ ; k++) + data_out[j][i][k] = 0; + } + } + + /* Create access property list and set the driver to GASS */ + fapl = H5Pcreate (H5P_FILE_ACCESS); + if (fapl < 0) { + printf (" H5Pcreate failed. \n"); + return -1; + } + + + ginf.block_size = 0; + ginf.max_length =0; + + /* ginf = GASS_INFO_NULL; */ + + status = H5Pset_fapl_gass (fapl, ginf); + if (status < 0) { + printf ("H5Pset_fapl_gass failed. \n"); + return -1; + } + + /* + * Open the file and the dataset. + */ + file = H5Fopen(URL, H5F_ACC_RDONLY, fapl); + dataset = H5Dopen(file, DATASETNAME); + + /* + * Get datatype and dataspace handles and then query + * dataset class, order, size, rank and dimensions. + */ + datatype = H5Dget_type(dataset); /* datatype handle */ + class = H5Tget_class(datatype); + if (class == H5T_INTEGER) printf("Data set has INTEGER type \n"); + order = H5Tget_order(datatype); + if (order == H5T_ORDER_LE) printf("Little endian order \n"); + + size = H5Tget_size(datatype); + printf(" Data size is %d \n", size); + + dataspace = H5Dget_space(dataset); /* dataspace handle */ + rank = H5Sget_simple_extent_ndims(dataspace); + status_n = H5Sget_simple_extent_dims(dataspace, dims_out, NULL); + printf("rank %d, dimensions %lu x %lu \n", rank, + (unsigned long)(dims_out[0]), (unsigned long)(dims_out[1])); + + /* + * Define hyperslab in the dataset. + */ + offset[0] = 1; + offset[1] = 2; + count[0] = NX_SUB; + count[1] = NY_SUB; + status = H5Sselect_hyperslab(dataspace, H5S_SELECT_SET, offset, NULL, + count, NULL); + + /* + * Define the memory dataspace. + */ + dimsm[0] = NX; + dimsm[1] = NY; + dimsm[2] = NZ ; + memspace = H5Screate_simple(RANK_OUT,dimsm,NULL); + + /* + * Define memory hyperslab. + */ + offset_out[0] = 3; + offset_out[1] = 0; + offset_out[2] = 0; + count_out[0] = NX_SUB; + count_out[1] = NY_SUB; + count_out[2] = 1; + status = H5Sselect_hyperslab(memspace, H5S_SELECT_SET, offset_out, NULL, + count_out, NULL); + + /* + * Read data from hyperslab in the file into the hyperslab in + * memory and display. + */ + status = H5Dread(dataset, H5T_NATIVE_INT, memspace, dataspace, + H5P_DEFAULT, data_out); + for (j = 0; j < NX; j++) { + for (i = 0; i < NY; i++) printf("%d ", data_out[j][i][0]); + printf("\n"); + } + /* + * 0 0 0 0 0 0 0 + * 0 0 0 0 0 0 0 + * 0 0 0 0 0 0 0 + * 3 4 5 6 0 0 0 + * 4 5 6 7 0 0 0 + * 5 6 7 8 0 0 0 + * 0 0 0 0 0 0 0 + */ + + /* + * Close/release resources. + */ + H5Tclose(datatype); + H5Dclose(dataset); + H5Sclose(dataspace); + H5Sclose(memspace); + H5Fclose(file); + H5Pclose(fapl); + + return 0; +} +#endif diff --git a/test/gass_write.c b/test/gass_write.c new file mode 100644 index 0000000..a6000ed --- /dev/null +++ b/test/gass_write.c @@ -0,0 +1,157 @@ +/* + * Copyright © 1998 NCSA + * All rights reserved. + * + * Programmer: Saurabh Bagchi (bagchi@uiuc.edu) + * Friday, August 6, 1999. + * + * Modifications: Saurabh Bagchi (Aug 17, 1999) + * Modified to work with VFL (HDF51.3). + */ + +/* Test the following functionality of the GASS driver. + 1. Open a remote file for write. + 2. Create a new dataset within the file. + 3. Create a local memory buffer to hold the data. + 4. Write the local data to the remote dataset. +*/ +#include + +#ifndef HAVE_GASS +int main(void) +{ + printf("Test skipped because GASS driver not available\n"); + return 0; +} +#else + +#define URL "ftp://bagchi:bagchi12@hdfspare1/scratch-fuga/home/bagchi/junk.w" + +#define DATASETNAME "IntArray" +#define NX 5 /* dataset dimensions */ +#define NY 6 +#define RANK 2 + +int main (void) +{ + + hid_t fapl =-1, file; + hid_t dataspace, datatype, dataset; + hsize_t dimsf[2]; + + herr_t status = 0; + int data[NX][NY]; /* data to write */ + int i, j; + GASS_Info ginf; + + /* + * Data and output buffer initialization. + */ + for (j = 0; j < NX; j++) { + for (i = 0; i < NY; i++) + data[j][i] = i + j; + } + /* + * 0 1 2 3 4 5 + * 1 2 3 4 5 6 + * 2 3 4 5 6 7 + * 3 4 5 6 7 8 + * 4 5 6 7 8 9 + */ + + /* Create access property list and set the driver to GASS */ + fapl = H5Pcreate (H5P_FILE_ACCESS); + if (fapl < 0) { + printf (" H5Pcreate failed. \n"); + return -1; + } + + ginf.block_size = 0; + ginf.max_length =0; + /* ginf = GASS_INFO_NULL;*/ + + status = H5Pset_fapl_gass (fapl, ginf); + if (status < 0) { + printf ("H5Pset_fapl_gass failed. \n"); + return -1; + } + + /* + * Create a new file using H5F_ACC_TRUNC access, + * default file creation properties, and gass file + * access properties. + */ + // file = H5Fcreate(URL, H5F_ACC_TRUNC, H5P_DEFAULT, fapl); + // Works. Truncates existing files. + // file = H5Fcreate(URL, H5F_ACC_EXCL, H5P_DEFAULT, fapl); + // Works. Croaks if existing file, else creates. + // Any other flag has no effect as long as one and exactly one of TRUNC/ + // EXCL is there + /* printf ("I'm here just before H5Fcreate. \n");*/ + file = H5Fcreate(URL, H5F_ACC_TRUNC, H5P_DEFAULT, fapl); + if (file < 0) { + printf ("H5Fcreate failed. \n"); + return -1; + } + + /* + * Describe the size of the array and create the data space for fixed + * size dataset. + */ + dimsf[0] = NX; + dimsf[1] = NY; + dataspace = H5Screate_simple(RANK, dimsf, NULL); + if (dataspace < 0) { + printf ("H5Screate failed. \n"); + return -1; + } + + /* + * Define datatype for the data in the file. + * We will store little endian INT numbers. + */ + datatype = H5Tcopy(H5T_NATIVE_INT); + if (datatype < 0) { + printf ("H5Tcopy failed. \n"); + return -1; + } + + status = H5Tset_order(datatype, H5T_ORDER_LE); + if (status < 0) { + printf ("H5Tset_order failed. \n"); + return -1; + } + + /* + * Create a new dataset within the file using defined dataspace and + * datatype and default dataset creation properties. + */ + dataset = H5Dcreate(file, DATASETNAME, datatype, dataspace, + H5P_DEFAULT); + if (dataset < 0) { + printf ("H5Dcreate failed. \n"); + return -1; + } + + /* + * Write the data to the dataset using default transfer properties. + */ + status = H5Dwrite(dataset, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, + H5P_DEFAULT, data); + if (status < 0) { + printf ("H5Dwrite failed. \n"); + return -1; + } + + /* + * Close/release resources. + */ + H5Sclose(dataspace); + H5Tclose(datatype); + H5Dclose(dataset); + H5Fclose(file); + H5Pclose(fapl); + + return 0; +} +#endif -- cgit v0.12