diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/H5C.c | 378 | ||||
-rw-r--r-- | src/H5Cprivate.h | 1 | ||||
-rw-r--r-- | src/H5Cpublic.h | 5 | ||||
-rw-r--r-- | src/H5E.c | 1 | ||||
-rw-r--r-- | src/H5Epublic.h | 1 | ||||
-rw-r--r-- | src/H5F.c | 1848 | ||||
-rw-r--r-- | src/H5Fcore.c | 90 | ||||
-rw-r--r-- | src/H5Ffamily.c | 678 | ||||
-rw-r--r-- | src/H5Flow.c | 110 | ||||
-rw-r--r-- | src/H5Fmpio.c | 112 | ||||
-rw-r--r-- | src/H5Fprivate.h | 131 | ||||
-rw-r--r-- | src/H5Fpublic.h | 50 | ||||
-rw-r--r-- | src/H5Fsec2.c | 265 | ||||
-rw-r--r-- | src/H5Fstdio.c | 315 | ||||
-rw-r--r-- | src/H5MF.c | 3 | ||||
-rw-r--r-- | src/H5config.h.in | 6 | ||||
-rw-r--r-- | src/H5private.h | 9 | ||||
-rw-r--r-- | src/H5public.h | 4 |
18 files changed, 2359 insertions, 1648 deletions
@@ -58,6 +58,16 @@ H5C_init_interface(void) FUNC_ENTER(H5C_init_interface, FAIL); + /* + * Make sure the file creation and file access default templates are + * initialized since this might be done at run-time instead of compile + * time. + */ + if (H5F_init_interface ()<0) { + HRETURN_ERROR (H5E_INTERNAL, H5E_CANTINIT, FAIL, + "unable to initialize H5F and H5C interfaces"); + } + assert(H5C_NCLASSES <= H5_TEMPLATE_MAX - H5_TEMPLATE_0); /* @@ -66,14 +76,15 @@ H5C_init_interface(void) * atom groups aren't. */ for (i = 0; i < H5C_NCLASSES; i++) { - status = H5A_init_group((group_t)(H5_TEMPLATE_0 +i), H5A_TEMPID_HASHSIZE, 0, NULL); - if (status < 0) - ret_value = FAIL; + status = H5A_init_group((group_t)(H5_TEMPLATE_0 +i), + H5A_TEMPID_HASHSIZE, 0, NULL); + if (status < 0) ret_value = FAIL; } if (ret_value < 0) { HRETURN_ERROR(H5E_ATOM, H5E_CANTINIT, FAIL, "unable to initialize atom group"); } + /* * Register cleanup function. */ @@ -81,6 +92,7 @@ H5C_init_interface(void) HRETURN_ERROR(H5E_INTERNAL, H5E_CANTINIT, FAIL, "unable to install atexit function"); } + FUNC_LEAVE(ret_value); } @@ -194,7 +206,7 @@ H5Ccreate(H5C_class_t type) hid_t H5C_create(H5C_class_t type, void *tmpl) { - hid_t ret_value = FAIL; + hid_t ret_value = FAIL; FUNC_ENTER(H5C_create, FAIL); @@ -203,10 +215,11 @@ H5C_create(H5C_class_t type, void *tmpl) assert(tmpl); /* Atomize the new template */ - if ((ret_value = H5A_register((group_t)(H5_TEMPLATE_0 + type), tmpl)) < 0) { + if ((ret_value=H5A_register((group_t)(H5_TEMPLATE_0+type), tmpl)) < 0) { HRETURN_ERROR(H5E_ATOM, H5E_CANTINIT, FAIL, "can't register template"); } + FUNC_LEAVE(ret_value); } @@ -226,21 +239,79 @@ H5C_create(H5C_class_t type, void *tmpl) herr_t H5Cclose(hid_t tid) { - void *tmpl = NULL; + H5C_class_t type; + void *tmpl = NULL; FUNC_ENTER(H5Cclose, FAIL); - /* Chuck the object! :-) */ - if (NULL == (tmpl = H5A_remove(tid))) { - HRETURN_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "unable to remove atom"); + /* Check arguments */ + if ((type=H5Cget_class (tid))<0 || + NULL==(tmpl=H5A_object (tid))) { + HRETURN_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a property list"); } + + /* + * Chuck the object! This will fail when the reference count reaches zero + * since there is no free func registered for the property list groups. + */ + if (H5A_dec_ref (tid)<0) { + H5ECLEAR; + H5C_close (type, tmpl); + } + + FUNC_LEAVE (SUCCEED); +} + + +/*------------------------------------------------------------------------- + * Function: H5C_close + * + * Purpose: Closes a template and frees the memory associated with the + * template. + * + * Return: Success: SUCCEED + * + * Failure: FAIL + * + * Programmer: Robb Matzke + * Wednesday, February 18, 1998 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +herr_t +H5C_close (H5C_class_t type, void *tmpl) +{ + FUNC_ENTER (H5C_close, FAIL); + + /* Check args */ + assert (tmpl); + + /* Some templates may need to do special things */ + switch (type) { + case H5C_FILE_ACCESS: #ifdef LATER - /* this is for file access template too. Need to free the COMM and INFO objects too. */ -#endif - H5MM_xfree(tmpl); + /* Need to free the COMM and INFO objects too. */ +#endif + break; + + case H5C_FILE_CREATE: + case H5C_DATASET_CREATE: + case H5C_DATASET_XFER: + /*nothing to do*/ + break; + + default: + HRETURN_ERROR (H5E_ARGS, H5E_BADTYPE, FAIL, + "unknown property list class"); + } + /* Free the template struct and return */ + H5MM_xfree(tmpl); FUNC_LEAVE(SUCCEED); } + /*------------------------------------------------------------------------- * Function: H5Cget_class @@ -857,6 +928,235 @@ H5Cget_chunk(hid_t tid, int max_ndims, size_t dim[] /*out */ ) FUNC_LEAVE(tmpl->chunk_ndims); } + + +/*------------------------------------------------------------------------- + * Function: H5Cset_stdio + * + * Purpose: Set the low level file driver to use the functions declared + * in the stdio.h file: fopen(), fseek() or fseek64(), fread(), + * fwrite(), and fclose(). + * + * Return: Success: SUCCEED + * + * Failure: FAIL + * + * Programmer: Robb Matzke + * Thursday, February 19, 1998 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +herr_t +H5Cset_stdio (hid_t tid) +{ + H5F_access_t *tmpl = NULL; + + FUNC_ENTER (H5Cset_stdio, FAIL); + + /* Check arguments */ + if (H5C_FILE_ACCESS != H5Cget_class(tid) || + NULL == (tmpl = H5A_object(tid))) { + HRETURN_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, + "not a file access template"); + } + + /* Set driver */ + tmpl->driver = H5F_LOW_STDIO; + + FUNC_LEAVE (SUCCEED); +} + + +/*------------------------------------------------------------------------- + * Function: H5Cset_sec2 + * + * Purpose: Set the low-level file driver to use the functions declared + * in the unistd.h file: open(), lseek() or lseek64(), read(), + * write(), and close(). + * + * Return: Success: SUCCEED + * + * Failure: FAIL + * + * Programmer: Robb Matzke + * Thursday, February 19, 1998 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +herr_t +H5Cset_sec2 (hid_t tid) +{ + H5F_access_t *tmpl = NULL; + + FUNC_ENTER (H5Cset_sec2, FAIL); + + /* Check arguments */ + if (H5C_FILE_ACCESS != H5Cget_class(tid) || + NULL == (tmpl = H5A_object(tid))) { + HRETURN_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, + "not a file access template"); + } + + /* Set driver */ + tmpl->driver = H5F_LOW_SEC2; + + FUNC_LEAVE (SUCCEED); +} + + +/*------------------------------------------------------------------------- + * Function: H5Cset_core + * + * Purpose: Set the low-level file driver to use malloc() and free(). + * This driver is restricted to temporary files which are not + * larger than the amount of virtual memory available. The + * INCREMENT argument determines the file block size and memory + * will be allocated in multiples of INCREMENT bytes. A liberal + * INCREMENT results in fewer calls to realloc() and probably + * less memory fragmentation. + * + * Return: Success: SUCCEED + * + * Failure: FAIL + * + * Programmer: Robb Matzke + * Thursday, February 19, 1998 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +herr_t +H5Cset_core (hid_t tid, size_t increment) +{ + H5F_access_t *tmpl = NULL; + + FUNC_ENTER (H5Cset_core, FAIL); + + /* Check arguments */ + if (H5C_FILE_ACCESS != H5Cget_class(tid) || + NULL == (tmpl = H5A_object(tid))) { + HRETURN_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, + "not a file access template"); + } + if (increment<1) { + HRETURN_ERROR (H5E_ARGS, H5E_BADVALUE, FAIL, + "increment must be positive"); + } + + /* Set driver */ + tmpl->driver = H5F_LOW_CORE; + tmpl->u.core.increment = increment; + + FUNC_LEAVE (SUCCEED); +} + + +/*------------------------------------------------------------------------- + * Function: H5Cset_split + * + * Purpose: Set the low-level driver to split meta data from raw data, + * storing meta data in one file and raw data in another file. + * + * Return: Success: SUCCEED + * + * Failure: FAIL + * + * Programmer: Robb Matzke + * Thursday, February 19, 1998 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +herr_t +H5Cset_split (hid_t tid, hid_t meta_tid, hid_t raw_tid) +{ + H5F_access_t *tmpl = NULL; + H5F_access_t *meta_tmpl = NULL; + H5F_access_t *raw_tmpl = NULL; + + FUNC_ENTER (H5Cset_split, FAIL); + + /* Check arguments */ + if (H5C_FILE_ACCESS != H5Cget_class(tid) || + NULL == (tmpl = H5A_object(tid))) { + HRETURN_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, + "not a file access template"); + } + if (H5C_DEFAULT!=meta_tid && + (H5C_FILE_ACCESS != H5Cget_class(meta_tid) || + NULL == (tmpl = H5A_object(meta_tid)))) { + HRETURN_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, + "not a file access template"); + } + if (H5C_DEFAULT!=raw_tid && + (H5C_FILE_ACCESS != H5Cget_class(raw_tid) || + NULL == (tmpl = H5A_object(raw_tid)))) { + HRETURN_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, + "not a file access template"); + } + + /* Set driver */ + tmpl->driver = H5F_LOW_SPLIT; + tmpl->u.split.meta_access = H5C_copy (H5C_FILE_ACCESS, meta_tmpl); + tmpl->u.split.raw_access = H5C_copy (H5C_FILE_ACCESS, raw_tmpl); + + FUNC_LEAVE (SUCCEED); +} + + +/*------------------------------------------------------------------------- + * Function: H5Cset_family + * + * Purpose: Sets the low-level driver to stripe the hdf5 address space + * across a family of files. + * + * Return: Success: SUCCEED + * + * Failure: FAIL + * + * Programmer: Robb Matzke + * Thursday, February 19, 1998 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +herr_t +H5Cset_family (hid_t tid, hid_t memb_tid) +{ + + H5F_access_t *tmpl = NULL; + H5F_access_t *memb_tmpl = NULL; + + FUNC_ENTER (H5Cset_family, FAIL); + + /* Check arguments */ + if (H5C_FILE_ACCESS != H5Cget_class(tid) || + NULL == (tmpl = H5A_object(tid))) { + HRETURN_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, + "not a file access template"); + } + if (H5C_DEFAULT!=memb_tid && + (H5C_FILE_ACCESS != H5Cget_class(memb_tid) || + NULL == (tmpl = H5A_object(memb_tid)))) { + HRETURN_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, + "not a file access template"); + } + + /* Set driver */ + tmpl->driver = H5F_LOW_FAMILY; + tmpl->u.fam.memb_access = H5C_copy (H5C_FILE_ACCESS, memb_tmpl); + + FUNC_LEAVE (SUCCEED); +} + + #ifdef HAVE_PARALLEL /*------------------------------------------------------------------------- @@ -903,12 +1203,18 @@ H5Cget_chunk(hid_t tid, int max_ndims, size_t dim[] /*out */ ) * * Modifications: * + * Robb Matzke, 18 Feb 1998 + * Check all arguments before the template is updated so we don't leave + * the template in a bad state if something goes wrong. Also, the + * template data type changed to allow more generality so all the + * mpi-related stuff is in the `u.mpi' member. The `access_mode' will + * contain only mpi-related flags defined in H5Fpublic.h. + * *------------------------------------------------------------------------- */ herr_t H5Cset_mpi (hid_t tid, MPI_Comm comm, MPI_Info info, uintn access_mode) { - int i; H5F_access_t *tmpl = NULL; MPI_Comm lcomm; int mrc; /* MPI return code */ @@ -919,31 +1225,47 @@ H5Cset_mpi (hid_t tid, MPI_Comm comm, MPI_Info info, uintn access_mode) if (H5C_FILE_ACCESS != H5Cget_class(tid) || NULL == (tmpl = H5A_object(tid))) { HRETURN_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, - "not a file access template"); + "not a file access template"); } + switch (access_mode){ case H5ACC_INDEPENDENT: - /* fall through to next case */ case H5ACC_COLLECTIVE: - tmpl->access_mode = access_mode; - break; + /* okay */ + break; default: - HRETURN_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, - "unknown access_mode"); + HRETURN_ERROR (H5E_ARGS, H5E_BADVALUE, FAIL, + "invalid mpio access mode"); } - /* store a duplicate copy of comm so that user may freely modify comm after this */ - /* call. */ #ifdef LATER - /* need to verify comm and info contain sensible information */ - /* need to duplicate info too but don't know a quick way to do it now. */ + /* + * Need to verify comm and info contain sensible information. + */ #endif - if ((mrc = MPI_Comm_dup(comm, &lcomm)) != MPI_SUCCESS) + + + /* + * Everything looks good. Now go ahead and modify the access template. + */ + tmpl->driver = H5F_LOW_MPIO; + tmpl->u.mpio.access_mode = access_mode; + + /* + * Store a duplicate copy of comm so that user may freely modify comm + * after this call. + */ + if ((mrc = MPI_Comm_dup(comm, &lcomm)) != MPI_SUCCESS) { HRETURN_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "failure to duplicate communicator"); - tmpl->comm = comm; - tmpl->info = info; + } + tmpl->u.mpio.comm = comm; + +#ifdef LATER + /* Need to duplicate info too but don't know a quick way to do it now */ +#endif + tmpl->u.mpio.info = info; FUNC_LEAVE(SUCCEED); } @@ -1038,8 +1360,8 @@ H5C_copy (H5C_class_t type, const void *src) break; case H5C_FILE_ACCESS: - HRETURN_ERROR(H5E_INTERNAL, H5E_UNSUPPORTED, NULL, - "file access properties are not implemented yet"); + size = sizeof(H5F_access_t); + break; case H5C_DATASET_CREATE: size = sizeof(H5D_create_t); diff --git a/src/H5Cprivate.h b/src/H5Cprivate.h index 2c24a5b..a01df14 100644 --- a/src/H5Cprivate.h +++ b/src/H5Cprivate.h @@ -24,5 +24,6 @@ hid_t H5C_create (H5C_class_t type, void *tmpl); void *H5C_copy (H5C_class_t type, const void *src); +herr_t H5C_close (H5C_class_t type, void *tmpl); #endif diff --git a/src/H5Cpublic.h b/src/H5Cpublic.h index b3b5348..44444dc 100644 --- a/src/H5Cpublic.h +++ b/src/H5Cpublic.h @@ -61,6 +61,11 @@ herr_t H5Cset_layout (hid_t tid, H5D_layout_t layout); H5D_layout_t H5Cget_layout (hid_t tid); herr_t H5Cset_chunk (hid_t tid, int ndims, const size_t dim[]); int H5Cget_chunk (hid_t tid, int max_ndims, size_t dim[]/*out*/); +herr_t H5Cset_stdio (hid_t tid); +herr_t H5Cset_sec2 (hid_t tid); +herr_t H5Cset_core (hid_t tid, size_t increment); +herr_t H5Cset_split (hid_t tid, hid_t meta_tid, hid_t raw_tid); +herr_t H5Cset_family (hid_t tid, hid_t memb_tid); #ifdef HAVE_PARALLEL herr_t H5Cset_mpi (hid_t tid, MPI_Comm comm, MPI_Info info, uintn access_mode); /* herr_t H5Cget_mpi (hid_t tid, int *ik); */ /* not defined yet */ @@ -77,6 +77,7 @@ static const H5E_minor_mesg_t H5E_minor_mesg_g[] = {H5E_READERROR, "Read failed"}, {H5E_WRITEERROR, "Write failed"}, {H5E_CLOSEERROR, "Close failed"}, + {H5E_OVERFLOW, "Address overflowed"}, {H5E_CANTINIT, "Can't initialize interface"}, {H5E_ALREADYINIT, "Object already initialized"}, {H5E_BADATOM, "Can't find atom information"}, diff --git a/src/H5Epublic.h b/src/H5Epublic.h index 8a4c5b7..c71bd3a 100644 --- a/src/H5Epublic.h +++ b/src/H5Epublic.h @@ -76,6 +76,7 @@ typedef enum H5E_minor_t { H5E_READERROR, /*read failed */ H5E_WRITEERROR, /*write failed */ H5E_CLOSEERROR, /*close failed */ + H5E_OVERFLOW, /*address overflowed */ /* Function entry/exit interface errors */ H5E_CANTINIT, /*Can't initialize interface */ @@ -1,21 +1,21 @@ /**************************************************************************** -* 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. * +* 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. * * * MODIFICATIONS -* Robb Matzke, 30 Aug 1997 -* Added `ERRORS' fields to function prologues. -* * +* Robb Matzke, 30 Aug 1997 +* Added `ERRORS' fields to function prologues. +* * ****************************************************************************/ #ifdef RCSID -static char RcsId[] = "@(#)$Revision$"; +static char RcsId[] = "@(#)$Revision$"; #endif /* $Id$ */ @@ -27,24 +27,24 @@ static char RcsId[] = "@(#)$Revision$"; HDF5 file I/O routines EXPORTED ROUTINES - H5Fcreate -- Create an HDF5 file - H5Fclose -- Close an open HDF5 file + H5Fcreate -- Create an HDF5 file + H5Fclose -- Close an open HDF5 file LIBRARY-SCOPED ROUTINES LOCAL ROUTINES - H5F_init_interface -- initialize the H5F interface + H5F_init_interface -- initialize the H5F interface */ /* Packages needed by this file... */ -#include <H5private.h> /*library functions */ -#include <H5Aprivate.h> /*atoms */ -#include <H5ACprivate.h> /*cache */ -#include <H5Cprivate.h> /*templates */ -#include <H5Eprivate.h> /*error handling */ -#include <H5Gprivate.h> /*symbol tables */ -#include <H5Mprivate.h> /*meta data */ -#include <H5MMprivate.h> /*core memory management */ +#include <H5private.h> /*library functions */ +#include <H5Aprivate.h> /*atoms */ +#include <H5ACprivate.h> /*cache */ +#include <H5Cprivate.h> /*templates */ +#include <H5Eprivate.h> /*error handling */ +#include <H5Gprivate.h> /*symbol tables */ +#include <H5Mprivate.h> /*meta data */ +#include <H5MMprivate.h> /*core memory management */ #include <ctype.h> #include <sys/types.h> @@ -57,58 +57,53 @@ static char RcsId[] = "@(#)$Revision$"; */ /* #define H5F_OPT_SEEK */ -#define PABLO_MASK H5F_mask +#define PABLO_MASK H5F_mask -/*--------------------- Locally scoped variables -----------------------------*/ +/*-------------------- Locally scoped variables -----------------------------*/ /* * Define the default file creation template. */ -const H5F_create_t H5F_create_dflt = { - 0, /* Default user-block size */ - 4, /* Default 1/2 rank for symtab leaf nodes */ - { /* Default 1/2 rank for btree intern nodes */ - 16, /* Symbol table internal nodes */ - 32, /* Indexed storage internal nodes */ - 0, /* unused */ - 0, /* unused */ - 0, /* unused */ - 0, /* unused */ - 0, /* unused */ - 0, /* unused */ +const H5F_create_t H5F_create_dflt = { + 0, /* Default user-block size */ + 4, /* Default 1/2 rank for symtab leaf nodes */ + { /* Default 1/2 rank for btree intern nodes */ + 16, /* Symbol table internal nodes */ + 32, /* Indexed storage internal nodes */ + 0, /* unused */ + 0, /* unused */ + 0, /* unused */ + 0, /* unused */ + 0, /* unused */ + 0, /* unused */ }, - 4, /* Default offset size */ - 4, /* Default length 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 # */ + 4, /* Default offset size */ + 4, /* Default length 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 # */ }; /* - * Define the default file access template. + * Define the default file access template. The template is initialized by + * H5F_init_interface(). */ -const H5F_access_t H5F_access_dflt = -{ - H5ACC_DEFAULT, /* Default file access mode */ -#ifdef HAVE_PARALLEL - MPI_COMM_NULL, /* Default is not using MPIO */ - MPI_INFO_NULL, /* Default no info */ -#endif -}; +H5F_access_t H5F_access_dflt; /* Interface initialization */ -static intn interface_initialize_g = FALSE; +static intn interface_initialize_g = FALSE; #define INTERFACE_INIT H5F_init_interface -static herr_t H5F_init_interface(void); -static void H5F_term_interface(void); +static void H5F_term_interface(void); /* PRIVATE PROTOTYPES */ -static H5F_t *H5F_new(H5F_file_t *shared); -static H5F_t *H5F_dest(H5F_t *f); -static herr_t H5F_flush(H5F_t *f, hbool_t invalidate); -static herr_t H5F_locate_signature(H5F_low_t *f_handle, haddr_t *addr /*out */ ); +static H5F_t *H5F_new(H5F_file_t *shared); +static H5F_t *H5F_dest(H5F_t *f); +static herr_t H5F_flush(H5F_t *f, hbool_t invalidate); +static herr_t H5F_locate_signature(H5F_low_t *f_handle, + const H5F_access_t *access_parms, + haddr_t *addr/*out*/); /*-------------------------------------------------------------------------- @@ -130,19 +125,43 @@ Modifications: It was already H5F_mask for the PABLO_TRACE_ON call. --------------------------------------------------------------------------*/ -static herr_t +herr_t H5F_init_interface(void) { - herr_t ret_value = SUCCEED; + herr_t ret_value = SUCCEED; + FUNC_ENTER(H5F_init_interface, FAIL); /* Initialize the atom group for the file IDs */ - if ((ret_value = H5A_init_group(H5_FILE, H5A_FILEID_HASHSIZE, 0, - (herr_t (*)(void*))H5Fclose)) != FAIL) - ret_value = H5_add_exit(&H5F_term_interface); + if (H5A_init_group(H5_FILE, H5A_FILEID_HASHSIZE, 0, + (herr_t (*)(void*))H5Fclose)<0 || + H5_add_exit(H5F_term_interface)<0) { + HRETURN_ERROR (H5E_ATOM, H5E_CANTINIT, FAIL, + "unable to initialize interface"); + } + + /* Initialize the default file access template */ + H5F_access_dflt.driver = H5F_LOW_DFLT; + switch (H5F_LOW_DFLT) { + case H5F_LOW_STDIO: + case H5F_LOW_SEC2: + case H5F_LOW_CORE: + case H5F_LOW_SPLIT: + case H5F_LOW_FAMILY: + /* nothing more to init */ + break; + + case H5F_LOW_MPIO: +#ifdef HAVE_PARALLEL + H5F_access_dflt.u.mpio.access_mode = 0; + H5F_access_dflt.u.mpio.comm = MPI_COMM_NULL; + H5F_access_dflt.u.mpio.info = MPI_INFO_NULL; +#endif + break; + } FUNC_LEAVE(ret_value); -} /* H5F_init_interface */ +} /*-------------------------------------------------------------------------- @@ -174,9 +193,9 @@ H5F_term_interface(void) H5F_encode_length_unusual -- encode an unusual length size USAGE void H5F_encode_length_unusual(f, p, l) - const H5F_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 + const H5F_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 ERRORS @@ -188,89 +207,132 @@ H5F_term_interface(void) void H5F_encode_length_unusual(const H5F_t *f, uint8 **p, uint8 *l) { - intn i = (intn)H5F_SIZEOF_SIZE(f)-1; + intn i = (intn)H5F_SIZEOF_SIZE(f)-1; #ifdef WORDS_BIGENDIAN /* * For non-little-endian platforms, encode each byte in memory backwards. */ - for (; i >= 0; i--, (*p)++) - *(*p) = *(l + i); + for (; i >= 0; i--, (*p)++) *(*p) = *(l + i); #else /* platform has little-endian integers */ HDmemcpy(*p,l,i+1); *p+=(i+1); #endif -#ifdef LATER - done: - if (ret_value == FALSE) { /* Error condition cleanup */ - - } /* end if */ -#endif /* LATER */ - - /* Normal function cleanup */ - -} /* H5F_encode_length_unusual */ +} -/*-------------------------------------------------------------------------- - NAME - H5Fget_create_template - - PURPOSE - Get an atom for a copy of the file-creation template for this file - - USAGE - hid_t H5Fget_create_template(fid) - hid_t fid; IN: File ID - - ERRORS - ATOM BADATOM Can't get file struct. - FUNC CANTCREATE Can't create template. - FUNC CANTINIT Can't init template. - - 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. ---------------------------------------------------------------------------*/ +/*------------------------------------------------------------------------- + * Function: H5Fget_create_template + * + * Purpose: Get an atom for a copy of the file-creation template for this + * file. This function returns an atom with a copy of the + * template parameters used to create a file. + * + * Return: Success: template ID + * + * Failure: FAIL + * + * Programmer: Unknown + * + * Modifications: + * + * Robb Matzke, 18 Feb 1998 + * Calls H5C_copy() to copy the template and H5C_close() to free that + * template if an error occurs. + * + *------------------------------------------------------------------------- + */ hid_t H5Fget_create_template(hid_t fid) { - H5F_t *file = NULL; - hid_t ret_value = FAIL; - H5F_create_t *tmpl = NULL; + H5F_t *file = NULL; + hid_t ret_value = FAIL; + H5F_create_t *tmpl = NULL; FUNC_ENTER(H5Fget_create_template, FAIL); /* check args */ - if (H5_FILE != H5A_group(fid)) { - HRETURN_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "not a file"); - } - if (NULL == (file = H5A_object(fid))) { - HRETURN_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "can't get file struct"); + if (H5_FILE != H5A_group(fid) || NULL==(file=H5A_object (fid))) { + HRETURN_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file"); } + /* Create the template object to return */ - tmpl = H5MM_xmalloc(sizeof(H5F_create_t)); - *tmpl = file->shared->create_parms; + if (NULL==(tmpl=H5C_copy (H5C_FILE_CREATE, + &(file->shared->create_parms)))) { + HRETURN_ERROR (H5E_INTERNAL, H5E_CANTINIT, FAIL, + "unable to copy file creation properties"); + } + + /* Create an atom */ if ((ret_value = H5C_create(H5C_FILE_CREATE, tmpl)) < 0) { - HRETURN_ERROR(H5E_ATOM, H5E_CANTREGISTER, FAIL, - "can't register template"); + H5C_close (H5C_FILE_CREATE, tmpl); + HRETURN_ERROR(H5E_ATOM, H5E_CANTREGISTER, FAIL, + "unable to register property list"); } + FUNC_LEAVE(ret_value); } +/*------------------------------------------------------------------------- + * Function: H5Fget_access_template + * + * Purpose: Returns a copy of the file access template of the specified + * file. + * + * Return: Success: Object ID for a copy of the file access + * template. + * + * Failure: FAIL + * + * Programmer: Robb Matzke + * Wednesday, February 18, 1998 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +hid_t +H5Fget_access_template (hid_t file_id) +{ + H5F_t *f = NULL; + H5F_access_t *tmpl = NULL; + hid_t ret_value = FAIL; + + FUNC_ENTER (H5Fget_access_template, FAIL); + + /* Check args */ + if (H5_FILE!=H5A_group (file_id) || NULL==(f=H5A_object (file_id))) { + HRETURN_ERROR (H5E_ARGS, H5E_BADTYPE, FAIL, "not a file"); + } + + /* Create the template object to return */ + if (NULL==(tmpl=H5C_copy (H5C_FILE_ACCESS, + &(f->shared->access_parms)))) { + HRETURN_ERROR (H5E_INTERNAL, H5E_CANTINIT, FAIL, + "unable to copy file access properties"); + } + + /* Create an atom */ + if ((ret_value = H5C_create (H5C_FILE_ACCESS, tmpl))<0) { + H5C_close (H5C_FILE_ACCESS, tmpl); + HRETURN_ERROR (H5E_ATOM, H5E_CANTREGISTER, FAIL, + "unable to register property list"); + } + + FUNC_LEAVE (ret_value); +} + + /*-------------------------------------------------------------------------- NAME H5F_compare_files -- compare file objects for the atom API USAGE intn HPcompare_filename(obj, key) - const void * obj; IN: pointer to the file record - const void * key; IN: pointer to the search key + const void * obj; IN: pointer to the file record + const void * key; IN: pointer to the search key ERRORS @@ -283,55 +345,57 @@ H5Fget_create_template(hid_t fid) static intn H5F_compare_files(const void * _obj, const void * _key) { - const H5F_t *obj = (const H5F_t *) _obj; - const H5F_search_t *key = (const H5F_search_t *) _key; - int ret_value = FALSE; + const H5F_t *obj = (const H5F_t *) _obj; + const H5F_search_t *key = (const H5F_search_t *) _key; + int ret_value = FALSE; FUNC_ENTER(H5F_compare_files, FALSE); ret_value = (obj->shared->key.dev == key->dev && - obj->shared->key.ino == key->ino); + obj->shared->key.ino == key->ino); FUNC_LEAVE(ret_value); } /*------------------------------------------------------------------------- - * Function: H5F_locate_signature + * Function: H5F_locate_signature * - * Purpose: Finds the HDF5 boot block signature in a file. The signature - * can appear at address 0, or any power of two beginning with - * 512. + * Purpose: Finds the HDF5 boot block signature in a file. The signature + * can appear at address 0, or any power of two beginning with + * 512. * - * Return: Success: SUCCEED. The address of the signature is - * returned through the ADDR argument. + * Return: Success: SUCCEED. The address of the signature is + * returned through the ADDR argument. * - * Failure: FAIL + * Failure: FAIL * - * Programmer: Robb Matzke - * Friday, November 7, 1997 + * Programmer: Robb Matzke + * Friday, November 7, 1997 * * Modifications: * *------------------------------------------------------------------------- */ static herr_t -H5F_locate_signature(H5F_low_t *f_handle, haddr_t *addr /*out */ ) +H5F_locate_signature(H5F_low_t *f_handle, const H5F_access_t *access_parms, + haddr_t *addr/*out*/) { - haddr_t max_addr; - uint8 buf[H5F_SIGNATURE_LEN]; - uintn n = 9; + haddr_t max_addr; + uint8 buf[H5F_SIGNATURE_LEN]; + uintn n = 9; FUNC_ENTER(H5F_locate_signature, FAIL); H5F_low_size(f_handle, &max_addr); H5F_addr_reset(addr); while (H5F_addr_lt(addr, &max_addr)) { - if (H5F_low_read(f_handle, addr, H5F_SIGNATURE_LEN, buf) < 0) { - HRETURN_ERROR(H5E_IO, H5E_READERROR, FAIL, "can't read file"); - } - if (!HDmemcmp(buf, H5F_SIGNATURE, H5F_SIGNATURE_LEN)) - break; - H5F_addr_pow2(n++, addr); + if (H5F_low_read(f_handle, access_parms, addr, + H5F_SIGNATURE_LEN, buf) < 0) { + HRETURN_ERROR(H5E_IO, H5E_READERROR, FAIL, "can't read file"); + } + if (!HDmemcmp(buf, H5F_SIGNATURE, H5F_SIGNATURE_LEN)) + break; + H5F_addr_pow2(n++, addr); } FUNC_LEAVE(SUCCEED); @@ -347,14 +411,14 @@ H5F_locate_signature(H5F_low_t *f_handle, haddr_t *addr /*out */ ) USAGE hbool_t H5Fis_hdf5(filename) - const char *filename; IN: Name of the file to check + const char *filename; IN: Name of the file to check ERRORS - ARGS BADRANGE No filename specified. - FILE BADFILE Low-level file open failure. - IO READERROR Read error. - IO READERROR Seek error. - IO SEEKERROR Unable to determine length of file due to seek - failure. + ARGS BADRANGE No filename specified. + FILE BADFILE Low-level file open failure. + IO READERROR Read error. + IO READERROR Seek error. + IO SEEKERROR Unable to determine length of file due to seek + failure. RETURNS TRUE/FALSE/FAIL @@ -365,71 +429,80 @@ H5F_locate_signature(H5F_low_t *f_handle, haddr_t *addr /*out */ ) hbool_t H5Fis_hdf5(const char *filename) { - H5F_low_t *f_handle = NULL; /* file handle */ - haddr_t addr; /* Address of file signature & header */ - hbool_t ret_value = FALSE; + H5F_low_t *f_handle = NULL; /* file handle */ + haddr_t addr; /* Address of file signature & header */ + hbool_t ret_value = FALSE; + const H5F_low_class_t *type = NULL; FUNC_ENTER(H5Fis_hdf5, FAIL); /* Check args and all the boring stuff. */ - if (filename == NULL) - HGOTO_ERROR(H5E_ARGS, H5E_BADRANGE, FAIL, "no filename specified"); + if (filename == NULL) { + HGOTO_ERROR(H5E_ARGS, H5E_BADRANGE, FAIL, "no filename specified"); + } - /* Open the file */ - if (NULL == (f_handle = H5F_low_open(H5F_LOW_DFLT, filename, 0, NULL))) { - HGOTO_ERROR(H5E_FILE, H5E_BADFILE, FAIL, - "low-level file open failure"); + /* Open the file at the low level driver */ + type = H5F_low_class (H5F_access_dflt.driver); + assert (type); + if (NULL == (f_handle = H5F_low_open(type, filename, &H5F_access_dflt, + 0, NULL))) { + HGOTO_ERROR(H5E_FILE, H5E_BADFILE, FAIL, + "low-level file open failure"); } - if (H5F_locate_signature(f_handle, &addr) >= 0) { - ret_value = TRUE; + if (H5F_locate_signature(f_handle, &H5F_access_dflt, &addr) >= 0) { + ret_value = TRUE; } + done: - H5F_low_close(f_handle); /* close the file we opened */ + if (f_handle) { + H5F_low_close(f_handle, &H5F_access_dflt); /*close the file we opened*/ + } + FUNC_LEAVE(ret_value); } /*------------------------------------------------------------------------- - * Function: H5F_new + * Function: H5F_new * - * Purpose: Creates a new file object and initializes it. The - * H5Fopen and H5Fcreate functions then fill in various - * fields. If SHARED is a non-null pointer then the shared info - * to which it points has the reference count incremented. - * Otherwise a new, empty shared info struct is created. + * Purpose: Creates a new file object and initializes it. The + * H5Fopen and H5Fcreate functions then fill in various + * fields. If SHARED is a non-null pointer then the shared info + * to which it points has the reference count incremented. + * Otherwise a new, empty shared info struct is created. * * Errors: * - * Return: Success: Ptr to a new file struct. + * Return: Success: Ptr to a new file struct. * - * Failure: NULL + * Failure: NULL * - * Programmer: Robb Matzke - * matzke@llnl.gov - * Jul 18 1997 + * Programmer: Robb Matzke + * matzke@llnl.gov + * Jul 18 1997 * * Modifications: * *------------------------------------------------------------------------- */ -static H5F_t * +static H5F_t * H5F_new(H5F_file_t *shared) { - H5F_t *f = NULL; + H5F_t *f = NULL; FUNC_ENTER(H5F_new, NULL); f = H5MM_xcalloc(1, sizeof(H5F_t)); f->shared = shared; if (!f->shared) { - f->shared = H5MM_xcalloc(1, sizeof(H5F_file_t)); - H5F_addr_undef(&(f->shared->boot_addr)); - H5F_addr_undef(&(f->shared->base_addr)); - H5F_addr_undef(&(f->shared->smallobj_addr)); - H5F_addr_undef(&(f->shared->freespace_addr)); - H5F_addr_undef(&(f->shared->hdf5_eof)); - - /* Create a main cache */ - H5AC_create(f, H5AC_NSLOTS); + f->shared = H5MM_xcalloc(1, sizeof(H5F_file_t)); + H5F_addr_undef(&(f->shared->boot_addr)); + H5F_addr_undef(&(f->shared->base_addr)); + H5F_addr_undef(&(f->shared->smallobj_addr)); + H5F_addr_undef(&(f->shared->freespace_addr)); + H5F_addr_undef(&(f->shared->hdf5_eof)); + + /* Create a main cache */ + H5AC_create(f, H5AC_NSLOTS); } f->shared->nrefs++; @@ -437,221 +510,174 @@ H5F_new(H5F_file_t *shared) } /*------------------------------------------------------------------------- - * Function: H5F_dest + * 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. The shared info for the file is freed - * only when its reference count reaches zero. + * Purpose: Destroys a file structure. This function does not flush + * the cache or anything else; it only frees memory associated + * with the file struct. The shared info for the file is freed + * only when its reference count reaches zero. * * Errors: * - * Return: Success: NULL + * Return: Success: NULL * - * Failure: NULL + * Failure: NULL * - * Programmer: Robb Matzke - * matzke@llnl.gov - * Jul 18 1997 + * Programmer: Robb Matzke + * matzke@llnl.gov + * Jul 18 1997 * * Modifications: * *------------------------------------------------------------------------- */ -static H5F_t * +static H5F_t * H5F_dest(H5F_t *f) { FUNC_ENTER(H5F_dest, NULL); if (f) { - if (0 == --(f->shared->nrefs)) { - H5AC_dest(f); - f->shared->root_ent = H5MM_xfree(f->shared->root_ent); - f->shared = H5MM_xfree(f->shared); - } - f->name = H5MM_xfree(f->name); - H5MM_xfree(f); + if (0 == --(f->shared->nrefs)) { + H5AC_dest(f); + f->shared->root_ent = H5MM_xfree(f->shared->root_ent); + f->shared = H5MM_xfree(f->shared); + } + f->name = H5MM_xfree(f->name); + H5MM_xfree(f); } FUNC_LEAVE(NULL); } /*------------------------------------------------------------------------- - * Function: H5F_open - * - * Purpose: Opens (or creates) a file. This function understands the - * following flags which are similar in nature to the Posix - * open(2) flags. + * Function: H5F_open * - * H5F_ACC_WRITE: Open with read/write access. If the file is - * currently open for read-only access then it - * will be reopened. Absence of this flag - * implies read-only access. + * Purpose: Opens (or creates) a file. This function understands the + * following flags which are similar in nature to the Posix + * open(2) flags. * - * H5F_ACC_CREAT: Create a new file if it doesn't exist yet. - * The permissions are 0666 bit-wise AND with - * the current umask. H5F_ACC_WRITE must also - * be specified. + * H5F_ACC_WRITE: Open with read/write access. If the file is + * currently open for read-only access then it + * will be reopened. Absence of this flag + * implies read-only access. * - * H5F_ACC_EXCL: This flag causes H5F_open() to fail if the - * file already exists. + * H5F_ACC_CREAT: Create a new file if it doesn't exist yet. + * The permissions are 0666 bit-wise AND with + * the current umask. H5F_ACC_WRITE must also + * be specified. * - * H5F_ACC_TRUNC: The file is truncated and a new HDF5 boot - * block is written. This operation will fail - * if the file is already open. + * H5F_ACC_EXCL: This flag causes H5F_open() to fail if the + * file already exists. * - * Unlinking the file name from the group directed graph while - * the file is opened causes the file to continue to exist but - * one will not be able to upgrade the file from read-only - * access to read-write access by reopening it. Disk resources - * for the file are released when all handles to the file are - * closed. NOTE: This paragraph probably only applies to Unix; - * deleting the file name in other OS's has undefined results. + * H5F_ACC_TRUNC: The file is truncated and a new HDF5 boot + * block is written. This operation will fail + * if the file is already open. * - * The CREATE_PARMS argument is optional. A null pointer will - * cause the default file creation parameters to be used. + * Unlinking the file name from the group directed graph while + * the file is opened causes the file to continue to exist but + * one will not be able to upgrade the file from read-only + * access to read-write access by reopening it. Disk resources + * for the file are released when all handles to the file are + * closed. NOTE: This paragraph probably only applies to Unix; + * deleting the file name in other OS's has undefined results. * - * The ACCESS_PARMS argument is not used yet. + * The CREATE_PARMS argument is optional. A null pointer will + * cause the default file creation parameters to be used. * - * The TYPE argument determins the low-level type of file that - * is opened. The special value H5F_LOW_DFLT uses the default - * method which is defined at compile time. + * The ACCESS_PARMS argument is optional. A null pointer will + * cause the default file access parameters to be used. * * Errors: - * ATOM BADATOM Can't unatomize default template - * id. - * FILE BADVALUE Can't create file without write - * intent. - * FILE BADVALUE Can't truncate without write intent. - * FILE CANTCREATE Can't create file. - * FILE CANTCREATE Can't truncate file. - * FILE CANTINIT Can't get default file create template - * id. - * FILE CANTINIT Can't write file boot block. - * FILE CANTOPENFILE Bad address size. - * FILE CANTOPENFILE Bad boot block version number. - * FILE CANTOPENFILE Bad free space version number. - * FILE CANTOPENFILE Bad length size. - * FILE CANTOPENFILE Bad object dir version number. - * FILE CANTOPENFILE Bad shared header version number. - * FILE CANTOPENFILE Bad small object heap version number. - * FILE CANTOPENFILE Bad symbol table internal node 1/2 - * rank. - * FILE CANTOPENFILE Bad symbol table leaf node 1/2 rank. - * FILE CANTOPENFILE Can't read root symbol entry. - * FILE CANTOPENFILE Cannot open existing file. - * FILE CANTOPENFILE File cannot be reopened with write - * access. - * FILE CANTOPENFILE File does not exist. - * FILE CANTOPENFILE Invalid file family name. - * FILE FILEEXISTS File already exists - CREAT EXCL - * failed. - * FILE FILEOPEN File already open - TRUNC failed. - * FILE NOTHDF5 Can't find signature. - * FILE NOTHDF5 Can't read boot block. - * FILE READERROR File is not readable. - * FILE TRUNCATED Truncated file? - * FILE WRITEERROR File is not writable. - * IO READERROR Can't read boot block. - * - * Return: Success: Ptr to the file pointer. - * - * Failure: NULL - * - * Programmer: Robb Matzke - * Tuesday, September 23, 1997 + * ATOM BADATOM Can't unatomize default template + * id. + * FILE BADVALUE Can't create file without write + * intent. + * FILE BADVALUE Can't truncate without write intent. + * FILE CANTCREATE Can't create file. + * FILE CANTCREATE Can't truncate file. + * FILE CANTINIT Can't get default file create template + * id. + * FILE CANTINIT Can't write file boot block. + * FILE CANTOPENFILE Bad address size. + * FILE CANTOPENFILE Bad boot block version number. + * FILE CANTOPENFILE Bad free space version number. + * FILE CANTOPENFILE Bad length size. + * FILE CANTOPENFILE Bad object dir version number. + * FILE CANTOPENFILE Bad shared header version number. + * FILE CANTOPENFILE Bad small object heap version number. + * FILE CANTOPENFILE Bad symbol table internal node 1/2 + * rank. + * FILE CANTOPENFILE Bad symbol table leaf node 1/2 rank. + * FILE CANTOPENFILE Can't read root symbol entry. + * FILE CANTOPENFILE Cannot open existing file. + * FILE CANTOPENFILE File cannot be reopened with write + * access. + * FILE CANTOPENFILE File does not exist. + * FILE CANTOPENFILE Invalid file family name. + * FILE FILEEXISTS File already exists - CREAT EXCL + * failed. + * FILE FILEOPEN File already open - TRUNC failed. + * FILE NOTHDF5 Can't find signature. + * FILE NOTHDF5 Can't read boot block. + * FILE READERROR File is not readable. + * FILE TRUNCATED Truncated file? + * FILE WRITEERROR File is not writable. + * IO READERROR Can't read boot block. + * + * Return: Success: Ptr to the file pointer. + * + * Failure: NULL + * + * Programmer: Robb Matzke + * Tuesday, September 23, 1997 * * Modifications: * - * Robb Matzke, 11 Nov 1997 - * If the name contains the pattern /[^%]%\d*[duxX]/ then the file is - * assumed to be a family of files. The TYPE argument is ignored and - * H5F_LOW_FAM is used instead. + * Robb Matzke, 11 Nov 1997 + * If the name contains the pattern /[^%]%\d*[duxX]/ then the file is + * assumed to be a family of files. The TYPE argument is ignored and + * H5F_LOW_FAM is used instead. + * + * Albert Cheng, 5 Feb 1998 + * Added the access_parms argument to pass down access template + * information. * - * Albert Cheng, 5 Feb 1998 - * Added the access_parms argument to pass down access template - * information. + * Robb Matzke, 18 Feb 1998 + * The H5F_access_t changed to allow more generality. The low level + * driver is part of the file access template so the TYPE argument has + * been removed. * *------------------------------------------------------------------------- */ -H5F_t * -H5F_open(const H5F_low_class_t *type, const char *name, uintn flags, - const H5F_create_t *create_parms, const H5F_access_t *access_parms) +H5F_t * +H5F_open(const char *name, uintn flags, + const H5F_create_t *create_parms, const H5F_access_t *access_parms) { - H5F_t *f = NULL; /*return value */ - H5F_t *ret_value = NULL; /*a copy of `f' */ - H5F_t *old = NULL; /*a file already opened */ - H5F_search_t search; /*file search key */ - H5F_low_t *fd = NULL; /*low level file desc */ - hbool_t empty_file = FALSE; /*is file empty? */ - hbool_t file_exists = FALSE; /*file already exists */ - uint8 buf[256]; /*I/O buffer.. */ - const uint8 *p = NULL; /* ..and pointer into it */ - size_t fixed_size = 24; /*size of fixed part of boot blk */ - size_t variable_size; /*variable part of boot block */ - H5F_create_t *cp = NULL; /*file creation parameters */ - haddr_t addr1, addr2; /*temporary address */ - H5G_entry_t root_ent; /*root symbol table entry */ - const char *s = name; + H5F_t *f = NULL; /*return value */ + H5F_t *ret_value = NULL; /*a copy of `f' */ + H5F_t *old = NULL; /*a file already opened */ + H5F_search_t search; /*file search key */ + H5F_low_t *fd = NULL; /*low level file desc */ + hbool_t empty_file = FALSE; /*is file empty? */ + hbool_t file_exists = FALSE; /*file already exists */ + uint8 buf[256]; /*I/O buffer.. */ + const uint8 *p = NULL; /* ..and pointer into it */ + size_t fixed_size = 24; /*size of fixed part of boot blk*/ + size_t variable_size; /*variable part of boot block */ + H5F_create_t *cp = NULL; /*file creation parameters */ + haddr_t addr1, addr2; /*temporary address */ + H5G_entry_t root_ent; /*root symbol table entry */ + const H5F_low_class_t *type = NULL; /*low-level file driver */ FUNC_ENTER(H5F_open, NULL); assert(name && *name); /* - * Does the name look like a family name? A family name always has a - * percent (not preceded by a percent) followed by an optional plus and/or - * minus, followed by optional digits, followed by the letter `d', `u', - * `x', or `X'. This is a printf() format for an integer. - */ - while (*s) { - if ('%' != *s++) - continue; - if ('%' == *s) { - s++; - continue; - } - while (*s && isdigit(*s)) - s++; - if ('d' != *s && 'u' != *s && 'x' != *s && 'X' != *s) - continue; - break; - } - if (*s) { -#ifdef H5F_DEBUG - if (type != H5F_LOW_FAM) { - fprintf(stderr, "HDF5-DIAG: opening a file family\n"); - } -#endif - type = H5F_LOW_FAM; - } else if (type == H5F_LOW_FAM) { - HRETURN_ERROR(H5E_FILE, H5E_CANTOPENFILE, NULL, - "invalid file family name"); - } - /* - * If the name ends with `.h5' and there's another file that ends with - * `.raw' then open the file as a split file. - */ - { - if (H5F_LOW_SPLIT != type && (s = strstr(name, ".h5")) && !s[3]) { - char fullname[4096]; - strncpy(fullname, name, s - name); - strcpy(fullname + (s - name), ".raw"); - if (H5F_low_access(H5F_LOW_DFLT, fullname, F_OK, NULL)) { -#ifdef H5F_DEBUG - fprintf(stderr, "HDF5-DIAG: opening a split file\n"); -#endif - fullname[s - name] = '\0'; - f = H5F_open(H5F_LOW_SPLIT, fullname, flags, create_parms, access_parms); - HRETURN(f); - } - } - } - - /* - * If no file creation parameters are supplied then use defaults. + * If no file creation parameters or file access parameters are supplied + * then use defaults. */ - if (!create_parms) - create_parms = &H5F_create_dflt; + if (!create_parms) create_parms = &H5F_create_dflt; + if (!access_parms) access_parms = &H5F_access_dflt; /* * Does the file exist? If so, get the device and i-node values so we can @@ -659,112 +685,119 @@ H5F_open(const H5F_low_class_t *type, const char *name, uintn flags, * with hard or soft links) it doesn't work to compare files based only on * their full path name. */ - file_exists = H5F_low_access(type, name, F_OK, &search); + type = H5F_low_class (access_parms->driver); + assert (type); + file_exists = H5F_low_access(type, name, access_parms, F_OK, &search); /* * Open the low-level file (if necessary) and create an H5F_t struct that * points to an H5F_file_t struct. */ if (file_exists) { - if (flags & H5F_ACC_EXCL) { - HRETURN_ERROR(H5E_FILE, H5E_FILEEXISTS, NULL, - "file already exists - CREAT EXCL failed"); - } - if (!H5F_low_access(type, name, R_OK, NULL)) { - HRETURN_ERROR(H5E_FILE, H5E_READERROR, NULL, - "file is not readable"); - } - if ((flags & H5F_ACC_WRITE) && - !H5F_low_access(type, name, W_OK, NULL)) { - HRETURN_ERROR(H5E_FILE, H5E_WRITEERROR, NULL, - "file is not writable"); - } - if ((old = H5A_search(H5_FILE, H5F_compare_files, &search))) { - if (flags & H5F_ACC_TRUNC) { - HRETURN_ERROR(H5E_FILE, H5E_FILEOPEN, NULL, - "file already open - TRUNC failed"); - } - if ((flags & H5F_ACC_WRITE) && - 0 == (old->shared->flags & H5F_ACC_WRITE)) { - if (NULL == (fd = H5F_low_open(type, name, H5F_ACC_WRITE, NULL))) { - HRETURN_ERROR(H5E_FILE, H5E_CANTOPENFILE, NULL, - "file cannot be reopened with write access"); - } - H5F_low_close(old->shared->lf); - old->shared->lf = fd; - old->shared->flags |= H5F_ACC_WRITE; - fd = NULL; /*so we don't close it during error */ - } - f = H5F_new(old->shared); - - } else if (flags & H5F_ACC_TRUNC) { - /* Truncate existing file */ - if (0 == (flags & H5F_ACC_WRITE)) { - HRETURN_ERROR(H5E_FILE, H5E_BADVALUE, NULL, - "can't truncate without write intent"); - } - fd = H5F_low_open(type, name, H5F_ACC_WRITE | H5F_ACC_TRUNC, NULL); - if (!fd) { - HRETURN_ERROR(H5E_FILE, H5E_CANTCREATE, NULL, - "can't truncate file"); - } - f = H5F_new(NULL); - f->shared->key = search; - f->shared->flags = flags; - f->shared->lf = fd; - empty_file = TRUE; - - } else { - fd = H5F_low_open(type, name, (flags & H5F_ACC_WRITE), NULL); - if (!fd) { - HRETURN_ERROR(H5E_FILE, H5E_CANTOPENFILE, NULL, - "cannot open existing file"); - } - f = H5F_new(NULL); - f->shared->key = search; - f->shared->flags = flags; - f->shared->lf = fd; - } + if (flags & H5F_ACC_EXCL) { + HRETURN_ERROR(H5E_FILE, H5E_FILEEXISTS, NULL, + "file already exists - CREAT EXCL failed"); + } + if (!H5F_low_access(type, name, access_parms, R_OK, NULL)) { + HRETURN_ERROR(H5E_FILE, H5E_READERROR, NULL, + "file is not readable"); + } + if ((flags & H5F_ACC_RDWR) && + !H5F_low_access(type, name, access_parms, W_OK, NULL)) { + HRETURN_ERROR(H5E_FILE, H5E_WRITEERROR, NULL, + "file is not writable"); + } + if ((old = H5A_search(H5_FILE, H5F_compare_files, &search))) { + if (flags & H5F_ACC_TRUNC) { + HRETURN_ERROR(H5E_FILE, H5E_FILEOPEN, NULL, + "file already open - TRUNC failed"); + } + if ((flags & H5F_ACC_RDWR) && + 0 == (old->shared->flags & H5F_ACC_RDWR)) { + if (NULL==(fd=H5F_low_open(type, name, access_parms, + H5F_ACC_RDWR, NULL))) { + HRETURN_ERROR(H5E_FILE, H5E_CANTOPENFILE, NULL, + "file cannot be reopened with write access"); + } + H5F_low_close(old->shared->lf, access_parms); + old->shared->lf = fd; + old->shared->flags |= H5F_ACC_RDWR; + fd = NULL; /*so we don't close it during error */ + } + f = H5F_new(old->shared); + + } else if (flags & H5F_ACC_TRUNC) { + /* Truncate existing file */ + if (0 == (flags & H5F_ACC_RDWR)) { + HRETURN_ERROR(H5E_FILE, H5E_BADVALUE, NULL, + "can't truncate without write intent"); + } + fd = H5F_low_open(type, name, access_parms, + H5F_ACC_RDWR | H5F_ACC_TRUNC, NULL); + if (!fd) { + HRETURN_ERROR(H5E_FILE, H5E_CANTCREATE, NULL, + "can't truncate file"); + } + f = H5F_new(NULL); + f->shared->key = search; + f->shared->flags = flags; + f->shared->lf = fd; + empty_file = TRUE; + + } else { + fd = H5F_low_open(type, name, access_parms, + (flags & H5F_ACC_RDWR), NULL); + if (!fd) { + HRETURN_ERROR(H5E_FILE, H5E_CANTOPENFILE, NULL, + "cannot open existing file"); + } + f = H5F_new(NULL); + f->shared->key = search; + f->shared->flags = flags; + f->shared->lf = fd; + } } else if (flags & H5F_ACC_CREAT) { - if (0 == (flags & H5F_ACC_WRITE)) { - HRETURN_ERROR(H5E_FILE, H5E_BADVALUE, NULL, - "can't create file without write intent"); - } + if (0 == (flags & H5F_ACC_RDWR)) { + HRETURN_ERROR(H5E_FILE, H5E_BADVALUE, NULL, + "can't create file without write intent"); + } #ifdef HAVE_PARALLEL - /* ROMIO cannot handle file-open with EXCL Create due to racing problem */ - /* The first process creates the file which then fails all */ - /* other processes. Turn on TRUNC bit here. It does not matter */ - /* since the file does not exist at this point. */ - fd = H5F_low_open(type, name, - H5F_ACC_WRITE | H5F_ACC_CREAT | + /* + * ROMIO cannot handle file-open with EXCL Create due to racing + * problem. The first process creates the file which then fails all + * other processes. Turn on TRUNC bit here. It does not matter since + * the file does not exist at this point. + */ + fd = H5F_low_open(type, name, access_parms, + H5F_ACC_RDWR | H5F_ACC_CREAT | (flags & H5F_ACC_TRUNC), - &search); + &search); #else - fd = H5F_low_open(type, name, - H5F_ACC_WRITE | H5F_ACC_CREAT | + fd = H5F_low_open(type, name, access_parms, + H5F_ACC_RDWR | H5F_ACC_CREAT | (flags & H5F_ACC_EXCL) | (flags & H5F_ACC_TRUNC), - &search); + &search); #endif /*HAVE_PARALLEL*/ - if (!fd) { - HRETURN_ERROR(H5E_FILE, H5E_CANTCREATE, NULL, - "can't create file"); - } - f = H5F_new(NULL); - f->shared->key = search; - f->shared->flags = flags; - f->shared->lf = fd; - empty_file = TRUE; + if (!fd) { + HRETURN_ERROR(H5E_FILE, H5E_CANTCREATE, NULL, + "can't create file"); + } + f = H5F_new(NULL); + f->shared->key = search; + f->shared->flags = flags; + f->shared->lf = fd; + empty_file = TRUE; } else { - HRETURN_ERROR(H5E_FILE, H5E_CANTOPENFILE, NULL, - "file does not exist"); + HRETURN_ERROR(H5E_FILE, H5E_CANTOPENFILE, NULL, + "file does not exist"); } assert(f); /* * The intent at the top level file struct are not necessarily the same as - * the flags at the bottom. The top level describes how the file can be + * the flags at the bottom. The top level describes how the file can be * accessed through the HDF5 library. The bottom level describes how the * file can be accessed through the C library. */ @@ -772,11 +805,12 @@ H5F_open(const H5F_low_class_t *type, const char *name, uintn flags, f->name = H5MM_xstrdup(name); /* - * Update the file creation parameters with default values if this is the - * first time this file is opened. + * Update the file creation parameters and file access parameters with + * default values if this is the first time this file is opened. */ if (1 == f->shared->nrefs) { - f->shared->create_parms = *create_parms; + f->shared->create_parms = *create_parms; + f->shared->access_parms = *access_parms; } cp = &(f->shared->create_parms); @@ -784,131 +818,140 @@ H5F_open(const H5F_low_class_t *type, const char *name, uintn flags, * Read or write the file boot block. */ if (empty_file) { - /* - * For new files we must write the boot block. The boot block starts - * immediately after the user-defined header, which we have already - * insured is a proper size. The base address is set to the same thing - * as the boot block. - */ - H5F_addr_reset(&(f->shared->boot_addr)); - H5F_addr_inc(&(f->shared->boot_addr), - f->shared->create_parms.userblock_size); - f->shared->base_addr = f->shared->boot_addr; - - f->shared->consist_flags = 0x03; - if (H5F_flush(f, FALSE) < 0) { - HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, NULL, - "can't write file boot block"); - } + /* + * For new files we must write the boot block. The boot block starts + * immediately after the user-defined header, which we have already + * insured is a proper size. The base address is set to the same thing + * as the boot block. + */ + H5F_addr_reset(&(f->shared->boot_addr)); + H5F_addr_inc(&(f->shared->boot_addr), + f->shared->create_parms.userblock_size); + f->shared->base_addr = f->shared->boot_addr; + + f->shared->consist_flags = 0x03; + if (H5F_flush(f, FALSE) < 0) { + HGOTO_ERROR(H5E_FILE, H5E_CANTINIT, NULL, + "can't write file boot block"); + } + } else if (1 == f->shared->nrefs) { - /* For existing files we must read the boot block. */ - if (H5F_locate_signature(f->shared->lf, &(f->shared->boot_addr)) < 0) { - HGOTO_ERROR(H5E_FILE, H5E_NOTHDF5, NULL, "can't find signature"); - } - if (H5F_low_read(f->shared->lf, &(f->shared->boot_addr), - fixed_size, buf) < 0) { - HGOTO_ERROR(H5E_IO, H5E_READERROR, NULL, "can't read boot block"); - } - /* - * Decode the fixed size part of the boot block. For each of the - * version parameters, check that the library is able to handle that - * version. - */ - p = buf + H5F_SIGNATURE_LEN; /*already checked */ - - cp->bootblock_ver = *p++; - if (cp->bootblock_ver != HDF5_BOOTBLOCK_VERSION) { - HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, NULL, - "bad boot block version number"); - } - cp->smallobject_ver = *p++; - if (cp->smallobject_ver != HDF5_SMALLOBJECT_VERSION) { - HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, NULL, - "bad small object heap version number"); - } - cp->freespace_ver = *p++; - if (cp->freespace_ver != HDF5_FREESPACE_VERSION) { - HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, NULL, - "bad free space version number"); - } - cp->objectdir_ver = *p++; - if (cp->objectdir_ver != HDF5_OBJECTDIR_VERSION) { - HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, NULL, - "bad object dir version number"); - } - cp->sharedheader_ver = *p++; - if (cp->sharedheader_ver != HDF5_SHAREDHEADER_VERSION) { - HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, NULL, - "bad shared header version number"); - } - cp->sizeof_addr = *p++; - if (cp->sizeof_addr != 2 && - cp->sizeof_addr != 4 && - cp->sizeof_addr != 8 && - cp->sizeof_addr != 16 && - cp->sizeof_addr != 32) { - HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, NULL, - "bad address size"); - } - cp->sizeof_size = *p++; - if (cp->sizeof_size != 2 && - cp->sizeof_size != 4 && - cp->sizeof_size != 8 && - cp->sizeof_size != 16 && - cp->sizeof_size != 32) { - HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, NULL, - "bad length size"); - } - /* Reserved byte */ - p++; - - UINT16DECODE(p, cp->sym_leaf_k); - if (cp->sym_leaf_k < 1) { - HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, NULL, - "bad symbol table leaf node 1/2 rank"); - } - UINT16DECODE(p, cp->btree_k[H5B_SNODE_ID]); - if (cp->btree_k[H5B_SNODE_ID] < 1) { - HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, NULL, - "bad symbol table internal node 1/2 rank"); - } - UINT32DECODE(p, f->shared->consist_flags); - /* nothing to check for consistency flags */ - - assert(p - buf == fixed_size); - - /* Read the variable length part of the boot block... */ - variable_size = H5F_SIZEOF_ADDR(f) + /*base address */ - H5F_SIZEOF_ADDR(f) + /*global small obj heap */ - H5F_SIZEOF_ADDR(f) + /*global free list addr */ - H5F_SIZEOF_ADDR(f) + /*logical file size */ - H5G_SIZEOF_ENTRY(f); - assert(variable_size <= sizeof buf); - addr1 = f->shared->boot_addr; - H5F_addr_inc(&addr1, fixed_size); - if (H5F_low_read(f->shared->lf, &addr1, variable_size, buf) < 0) { - HGOTO_ERROR(H5E_FILE, H5E_NOTHDF5, NULL, - "can't read boot block"); - } - p = buf; - H5F_addr_decode(f, &p, &(f->shared->base_addr)); - H5F_addr_decode(f, &p, &(f->shared->smallobj_addr)); - H5F_addr_decode(f, &p, &(f->shared->freespace_addr)); - H5F_addr_decode(f, &p, &(f->shared->hdf5_eof)); - if (H5G_ent_decode(f, &p, &root_ent) < 0) { - HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, NULL, - "can't read root symbol entry"); - } - if (H5F_addr_defined(&(root_ent.header))) { - f->shared->root_ent = H5MM_xmalloc(sizeof(H5G_entry_t)); - *(f->shared->root_ent) = root_ent; - } - /* - * The userdefined data is the area of the file before the base - * address. - */ - f->shared->create_parms.userblock_size = f->shared->base_addr.offset; + /* For existing files we must read the boot block. */ + if (H5F_locate_signature(f->shared->lf, + &(f->shared->access_parms), + &(f->shared->boot_addr)) < 0) { + HGOTO_ERROR(H5E_FILE, H5E_NOTHDF5, NULL, "can't find signature"); + } + if (H5F_low_read(f->shared->lf, access_parms, &(f->shared->boot_addr), + fixed_size, buf) < 0) { + HGOTO_ERROR(H5E_IO, H5E_READERROR, NULL, "can't read boot block"); + } + + /* + * Decode the fixed size part of the boot block. For each of the + * version parameters, check that the library is able to handle that + * version. + */ + p = buf + H5F_SIGNATURE_LEN; /*already checked */ + + cp->bootblock_ver = *p++; + if (cp->bootblock_ver != HDF5_BOOTBLOCK_VERSION) { + HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, NULL, + "bad boot block version number"); + } + cp->smallobject_ver = *p++; + if (cp->smallobject_ver != HDF5_SMALLOBJECT_VERSION) { + HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, NULL, + "bad small object heap version number"); + } + cp->freespace_ver = *p++; + if (cp->freespace_ver != HDF5_FREESPACE_VERSION) { + HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, NULL, + "bad free space version number"); + } + cp->objectdir_ver = *p++; + if (cp->objectdir_ver != HDF5_OBJECTDIR_VERSION) { + HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, NULL, + "bad object dir version number"); + } + cp->sharedheader_ver = *p++; + if (cp->sharedheader_ver != HDF5_SHAREDHEADER_VERSION) { + HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, NULL, + "bad shared header version number"); + } + cp->sizeof_addr = *p++; + if (cp->sizeof_addr != 2 && + cp->sizeof_addr != 4 && + cp->sizeof_addr != 8 && + cp->sizeof_addr != 16 && + cp->sizeof_addr != 32) { + HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, NULL, + "bad address size"); + } + cp->sizeof_size = *p++; + if (cp->sizeof_size != 2 && + cp->sizeof_size != 4 && + cp->sizeof_size != 8 && + cp->sizeof_size != 16 && + cp->sizeof_size != 32) { + HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, NULL, + "bad length size"); + } + + /* Reserved byte */ + p++; + + UINT16DECODE(p, cp->sym_leaf_k); + if (cp->sym_leaf_k < 1) { + HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, NULL, + "bad symbol table leaf node 1/2 rank"); + } + UINT16DECODE(p, cp->btree_k[H5B_SNODE_ID]); + if (cp->btree_k[H5B_SNODE_ID] < 1) { + HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, NULL, + "bad symbol table internal node 1/2 rank"); + } + UINT32DECODE(p, f->shared->consist_flags); + + /* nothing to check for consistency flags */ + + assert(p - buf == fixed_size); + + /* Read the variable length part of the boot block... */ + variable_size = H5F_SIZEOF_ADDR(f) + /*base address */ + H5F_SIZEOF_ADDR(f) + /*global small obj heap */ + H5F_SIZEOF_ADDR(f) + /*global free list addr */ + H5F_SIZEOF_ADDR(f) + /*logical file size */ + H5G_SIZEOF_ENTRY(f); + assert(variable_size <= sizeof buf); + addr1 = f->shared->boot_addr; + H5F_addr_inc(&addr1, fixed_size); + if (H5F_low_read(f->shared->lf, access_parms, &addr1, variable_size, + buf) < 0) { + HGOTO_ERROR(H5E_FILE, H5E_NOTHDF5, NULL, + "can't read boot block"); + } + p = buf; + H5F_addr_decode(f, &p, &(f->shared->base_addr)); + H5F_addr_decode(f, &p, &(f->shared->smallobj_addr)); + H5F_addr_decode(f, &p, &(f->shared->freespace_addr)); + H5F_addr_decode(f, &p, &(f->shared->hdf5_eof)); + if (H5G_ent_decode(f, &p, &root_ent) < 0) { + HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, NULL, + "can't read root symbol entry"); + } + if (H5F_addr_defined(&(root_ent.header))) { + f->shared->root_ent = H5MM_xmalloc(sizeof(H5G_entry_t)); + *(f->shared->root_ent) = root_ent; + } + + /* + * The userdefined data is the area of the file before the base + * address. + */ + f->shared->create_parms.userblock_size = f->shared->base_addr.offset; } + /* * What is the current size of the file? The max_addr field is a relative * address while H5F_low_size() returns an absolute address. @@ -917,265 +960,243 @@ H5F_open(const H5F_low_class_t *type, const char *name, uintn flags, addr2 = f->shared->hdf5_eof; H5F_addr_add(&addr2, &(f->shared->base_addr)); if (H5F_addr_lt(&addr1, &addr2)) { - /* - * Truncated file? This might happen if one tries to open the first - * member of a file family. - */ - HGOTO_ERROR(H5E_FILE, H5E_TRUNCATED, NULL, "truncated file"); + /* + * Truncated file? This might happen if one tries to open the first + * member of a file family. + */ + HGOTO_ERROR(H5E_FILE, H5E_TRUNCATED, NULL, "truncated file"); + } else if (H5F_addr_gt(&addr1, &addr2)) { - /* - * The file is larger than the hdf5 data. It either has extra junk at - * the end, or a wrapper. In either case, make the file think it's - * shorter so when we allocate memory from the file for hdf5 it's - * allocated immediately after the end of the previous hdf5 data. This - * will cause internal wrappers to be overwritten if they follow the - * hdf5 data. - */ + /* + * The file is larger than the hdf5 data. It either has extra junk at + * the end, or a wrapper. In either case, make the file think it's + * shorter so when we allocate memory from the file for hdf5 it's + * allocated immediately after the end of the previous hdf5 data. This + * will cause internal wrappers to be overwritten if they follow the + * hdf5 data. + */ #ifdef H5F_DEBUG - fprintf(stderr, "HDF5-DIAG: resetting EOF from "); - H5F_addr_print(stderr, &addr1); - fprintf(stderr, " to "); - H5F_addr_print(stderr, &addr2); - fprintf(stderr, " (abs)\n"); + fprintf(stderr, "HDF5-DIAG: resetting EOF from "); + H5F_addr_print(stderr, &addr1); + fprintf(stderr, " to "); + H5F_addr_print(stderr, &addr2); + fprintf(stderr, " (abs)\n"); #endif - H5F_low_seteof(f->shared->lf, &addr2); + H5F_low_seteof(f->shared->lf, &addr2); } + /* Success! */ ret_value = f; done: if (!ret_value) { - if (f) - H5F_dest(f); - H5F_low_close(fd); + if (f) H5F_dest(f); + H5F_low_close(fd, access_parms); } FUNC_LEAVE(ret_value); } -/*-------------------------------------------------------------------------- - NAME - H5Fcreate - - PURPOSE - Create a new HDF5 file. - - USAGE - int32 H5Fcreate(filename, flags, create_temp, access_temp) - const char *filename; IN: Name of the file to create - uintn flags; IN: Flags to indicate various options. - hid_t create_temp; IN: File-creation template ID - hid_t access_temp; IN: File-access template ID - - ERRORS - ARGS BADVALUE Invalid file name. - ARGS BADVALUE Invalid flags. - ATOM BADATOM Can't unatomize template. - ATOM CANTREGISTER Can't atomize file. - FILE CANTOPENFILE Can't create file. - - 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. The value - of 0 for a template value indicates that the library should use the default - values for the appropriate template. (Documented in the template module). - [Access templates are currently unused in this routine, although they will - be implemented in the future] - - 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(). - - Robb Matzke, 29 Aug 1997 - Moved creation of the boot block to H5F_flush(). - - Robb Matzke, 23 Sep 1997 - Most of the work is now done by H5F_open() since H5Fcreate() and H5Fopen() - originally contained almost identical code. ---------------------------------------------------------------------------*/ +/*------------------------------------------------------------------------- + * Function: H5Fcreate + * + * Purpose: 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 + * bit-wise OR operator (`|') to change the behavior of the file + * create call. + * + * The more complex behaviors of a file's creation and access + * are controlled through the file-creation and file-access + * property lists. The value of H5C_DEFAULT for a template + * value indicates that the library should use the default + * values for the appropriate template. + * + * See also: H5Fpublic.h for the list of supported flags. H5Cpublic.h for + * the list of file creation and file access properties. + * + * Return: Success: A file ID + * + * Failure: FAIL + * + * Programmer: Unknown + * + * 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(). + * + * Robb Matzke, 29 Aug 1997 + * Moved creation of the boot block to H5F_flush(). + * + * Robb Matzke, 23 Sep 1997 + * Most of the work is now done by H5F_open() since H5Fcreate() and + * H5Fopen() originally contained almost identical code. + * + * Robb Matzke, 18 Feb 1998 + * Better error checking for the creation and access property lists. It + * used to be possible to swap the two and core the library. Also, zero + * is no longer valid as a default property list; one must use + * H5C_DEFAULT instead. + * + *------------------------------------------------------------------------- + */ hid_t -H5Fcreate(const char *filename, uintn flags, hid_t create_temp, - hid_t access_temp) +H5Fcreate(const char *filename, uintn flags, hid_t create_id, + hid_t access_id) { - H5F_t *new_file = NULL; /* file struct for new file */ - const H5F_create_t *create_parms; /* pointer to the parameters to - * use when creating the file - */ - const H5F_access_t *access_parms; /* pointer to the file access - * parameters to use when creating - * the file - */ - const H5F_low_class_t *type; /* File type */ - hid_t ret_value = FAIL; + + H5F_t *new_file = NULL; /* file struct for new file */ + const H5F_create_t *create_parms; /* pointer to the parameters to + * use when creating the file + */ + const H5F_access_t *access_parms; /* pointer to the file access + * parameters to use when + * creating the file + */ + hid_t ret_value = FAIL; FUNC_ENTER(H5Fcreate, FAIL); /* Check/fix arguments */ - if (!filename || !*filename) - HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid file name"); - if (flags & ~H5ACC_OVERWRITE) - HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid flags"); - flags = (H5F_ACC_WRITE | H5F_ACC_CREAT) | - (H5ACC_OVERWRITE == flags ? H5F_ACC_TRUNC : H5F_ACC_EXCL); - - if (create_temp <= 0) { - create_parms = &H5F_create_dflt; - } else if (NULL == (create_parms = H5A_object(create_temp))) { - HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "can't unatomize template"); + if (!filename || !*filename) { + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid file name"); } - if (access_temp <= 0) { - access_parms = &H5F_access_dflt; - } else if (NULL == (access_parms = H5A_object(access_temp))) { - HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "can't unatomize template"); + if (flags & ~(H5F_ACC_EXCL|H5F_ACC_TRUNC)) { + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid flags"); } - /* figure out what kind of file I/O to use. */ - /* Currently, MPIO is the only alternative than default I/O */ - switch (access_parms->access_mode){ - case H5ACC_DEFAULT: - type = H5F_LOW_DFLT; - break; -#ifdef HAVE_PARALLEL - case H5ACC_INDEPENDENT: - type = H5F_LOW_MPIO; - break; - case H5ACC_COLLECTIVE: - /* not implemented yet */ - /* type = H5F_LOW_MPIO; */ - HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "Invalid file access mode"); -#endif - default: - HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "Invalid file access mode"); + if ((flags & H5F_ACC_EXCL) && (flags & H5F_ACC_EXCL)) { + HGOTO_ERROR (H5E_ARGS, H5E_BADVALUE, FAIL, + "mutually exclusive flags for file creation"); } - + if (H5C_DEFAULT==create_id) { + create_parms = &H5F_create_dflt; + } else if (H5C_FILE_CREATE!=H5Cget_class (create_id) || + NULL == (create_parms = H5A_object(create_id))) { + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, + "not a file creation property list"); + } + if (H5C_DEFAULT==access_id) { + access_parms = &H5F_access_dflt; + } else if (H5C_FILE_ACCESS!=H5Cget_class (access_id) || + NULL == (access_parms = H5A_object(access_id))) { + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, + "not a file access property list"); + } + + /* + * Adjust bit flags by turning on the creation bit and making sure that + * the EXCL or TRUNC bit is set. All newly-created files are opened for + * reading and writing. + */ + if (0==(flags & (H5F_ACC_EXCL|H5F_ACC_TRUNC))) { + flags |= H5F_ACC_EXCL; /*default*/ + } + flags |= H5F_ACC_RDWR | H5F_ACC_CREAT; + /* * Create a new file or truncate an existing file. */ - if (NULL == (new_file = H5F_open(type, filename, flags, - create_parms, access_parms))) { - HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, FAIL, "can't create file"); + if (NULL == (new_file = H5F_open(filename, flags, create_parms, + access_parms))) { + HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, FAIL, "unable to create file"); } + /* Get an atom for the file */ - if ((ret_value = H5A_register(H5_FILE, new_file)) < 0) - HGOTO_ERROR(H5E_ATOM, H5E_CANTREGISTER, FAIL, "can't atomize file"); + if ((ret_value = H5A_register(H5_FILE, new_file)) < 0) { + HGOTO_ERROR(H5E_ATOM, H5E_CANTREGISTER, FAIL, + "unable to atomize file"); + } done: if (ret_value < 0 && new_file) { - /* Error condition cleanup */ - H5F_close(new_file); + /* Error condition cleanup */ + H5F_close(new_file); } - /* Normal function cleanup */ FUNC_LEAVE(ret_value); } -/*-------------------------------------------------------------------------- - NAME - H5Fopen - - PURPOSE - Open an existing HDF5 file. - - USAGE - hid_t H5Fopen(filename, flags, access_temp) - const char *filename; IN: Name of the file to create - uintn flags; IN: Flags to indicate various options. - hid_t access_temp; IN: File-access template - - ERRORS - ARGS BADRANGE Invalid file name. - ATOM BADATOM Can't unatomize template. - ATOM CANTREGISTER Can't atomize file. - FILE CANTOPENFILE Cant open file. - - 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(). - - Robb Matzke, 23 Sep 1997 - Most of the work is now done by H5F_open() since H5Fcreate() and H5Fopen() - originally contained almost identical code. ---------------------------------------------------------------------------*/ +/*------------------------------------------------------------------------- + * Function: H5Fopen + * + * Purpose: This is the primary function for accessing existing HDF5 + * files. The FLAGS argument determines whether writing to an + * existing file will be allowed or not. All flags may be + * combined with the bit-wise OR operator (`|') to change the + * behavior of the file open call. The more complex behaviors + * of a file's access are controlled through the file-access + * property list. + * + * See Also: H5Fpublic.h for a list of possible values for FLAGS. + * + * Return: Success: A file ID + * + * Failure: FAIL + * + * Programmer: Unknown + * + * 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(). + * + * Robb Matzke, 23 Sep 1997 + * Most of the work is now done by H5F_open() since H5Fcreate() and + * H5Fopen() originally contained almost identical code. + * + * Robb Matzke, 18 Feb 1998 + * Added better error checking for the flags and the file access + * property list. It used to be possible to make the library dump core + * by passing an object ID that was not a file access property list. + * + *------------------------------------------------------------------------- + */ hid_t -H5Fopen(const char *filename, uintn flags, hid_t access_temp) +H5Fopen(const char *filename, uintn flags, hid_t access_id) { - H5F_t *new_file = NULL; /* file struct for new file */ - const H5F_access_t *access_parms; /* pointer to the file access - * parameters to use when creating - * the file - */ - const H5F_low_class_t *type; /* File type */ - hid_t ret_value = FAIL; + H5F_t *new_file = NULL; /* file struct for new file */ + const H5F_access_t *access_parms; /* pointer to the file access + * parameters to use when + * creating the file + */ + hid_t ret_value = FAIL; FUNC_ENTER(H5Fopen, FAIL); /* Check/fix arguments. */ - if (!filename || !*filename) - HGOTO_ERROR(H5E_ARGS, H5E_BADRANGE, FAIL, "invalid file name"); - flags = flags & H5ACC_WRITE ? H5F_ACC_WRITE : 0; - - if (access_temp <= 0) { - access_parms = &H5F_access_dflt; - } else if (NULL == (access_parms = H5A_object(access_temp))) { - HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "can't unatomize template"); + if (!filename || !*filename) { + HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid file name"); } - /* figure out what kind of file I/O to use. */ - /* Currently, MPIO is the only alternative than default I/O */ - switch (access_parms->access_mode){ - case H5ACC_DEFAULT: - type = H5F_LOW_DFLT; - break; -#ifdef HAVE_PARALLEL - case H5ACC_INDEPENDENT: - type = H5F_LOW_MPIO; - break; - case H5ACC_COLLECTIVE: - /* not implemented yet */ - /* type = H5F_LOW_MPIO; */ - HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "Invalid file access mode"); -#endif - default: - HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "Invalid file access mode"); + if ((flags & ~H5F_ACC_PUBLIC_FLAGS) || + (flags & H5F_ACC_TRUNC) || (flags & H5F_ACC_EXCL)) { + HGOTO_ERROR (H5E_ARGS, H5E_BADVALUE, FAIL, "invalid file open flags"); + } + if (H5C_DEFAULT==access_id) { + access_parms = &H5F_access_dflt; + } else if (H5C_FILE_ACCESS!=H5Cget_class (access_id) || + NULL == (access_parms = H5A_object(access_id))) { + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, + "not a file access property list"); } /* Open the file */ - if (NULL == (new_file = H5F_open(type, filename, flags, NULL, access_parms))) { - HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, FAIL, "cant open file"); + if (NULL==(new_file=H5F_open(filename, flags, NULL, access_parms))) { + HGOTO_ERROR(H5E_FILE, H5E_CANTOPENFILE, FAIL, "cant open file"); } + /* Get an atom for the file */ - if ((ret_value = H5A_register(H5_FILE, new_file)) < 0) - HGOTO_ERROR(H5E_ATOM, H5E_CANTREGISTER, FAIL, "can't atomize file"); + if ((ret_value = H5A_register(H5_FILE, new_file)) < 0) { + HGOTO_ERROR(H5E_ATOM, H5E_CANTREGISTER, FAIL, "can't atomize file"); + } - done: + done: if (ret_value < 0 && new_file) { - H5F_close(new_file); + H5F_close(new_file); } /* Normal function cleanup */ @@ -1183,23 +1204,23 @@ H5Fopen(const char *filename, uintn flags, hid_t access_temp) } /*------------------------------------------------------------------------- - * Function: H5F_flush + * Function: H5F_flush * - * Purpose: Flushes (and optionally invalidates) cached data plus the - * file boot block. If the logical file size field is zero - * then it is updated to be the length of the boot block. + * Purpose: Flushes (and optionally invalidates) cached data plus the + * file boot block. If the logical file size field is zero + * then it is updated to be the length of the boot block. * * Errors: - * CACHE CANTFLUSH Can't flush cache. - * IO WRITEERROR Can't write header. + * CACHE CANTFLUSH Can't flush cache. + * IO WRITEERROR Can't write header. * - * Return: Success: SUCCEED + * Return: Success: SUCCEED * - * Failure: FAIL + * Failure: FAIL * - * Programmer: Robb Matzke - * matzke@llnl.gov - * Aug 29 1997 + * Programmer: Robb Matzke + * matzke@llnl.gov + * Aug 29 1997 * * Modifications: * @@ -1208,23 +1229,24 @@ H5Fopen(const char *filename, uintn flags, hid_t access_temp) static herr_t H5F_flush(H5F_t *f, hbool_t invalidate) { - uint8 buf[2048], *p = buf; + uint8 buf[2048], *p = buf; FUNC_ENTER(H5F_flush, FAIL); /* - * Nothing to do if the file is read only. This determination is made at + * Nothing to do if the file is read only. This determination is made at * the shared open(2) flags level, implying that opening a file twice, * once for read-only and once for read-write, and then calling * H5F_flush() with the read-only handle, still causes data to be flushed. */ - if (0 == (H5F_ACC_WRITE & f->shared->flags)) - HRETURN(SUCCEED); + if (0 == (H5F_ACC_RDWR & f->shared->flags)) + HRETURN(SUCCEED); /* flush (and invalidate) the entire cache */ if (H5AC_flush(f, NULL, 0, invalidate) < 0) { - HRETURN_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "can't flush cache"); + HRETURN_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "can't flush cache"); } + /* encode the file boot block */ HDmemcpy(p, H5F_SIGNATURE, H5F_SIGNATURE_LEN); p += H5F_SIGNATURE_LEN; @@ -1238,7 +1260,7 @@ H5F_flush(H5F_t *f, hbool_t invalidate) *p++ = (uint8)H5F_SIZEOF_ADDR(f); assert (H5F_SIZEOF_SIZE(f)<=255); *p++ = (uint8)H5F_SIZEOF_SIZE(f); - *p++ = 0; /*reserved */ + *p++ = 0; /*reserved */ UINT16ENCODE(p, f->shared->create_parms.sym_leaf_k); UINT16ENCODE(p, f->shared->create_parms.btree_k[H5B_SNODE_ID]); UINT32ENCODE(p, f->shared->consist_flags); @@ -1250,32 +1272,35 @@ H5F_flush(H5F_t *f, hbool_t invalidate) /* update file length if necessary */ if (!H5F_addr_defined(&(f->shared->hdf5_eof))) { - H5F_addr_reset(&(f->shared->hdf5_eof)); - H5F_addr_inc(&(f->shared->hdf5_eof), p - buf); - H5F_low_seteof(f->shared->lf, &(f->shared->hdf5_eof)); + H5F_addr_reset(&(f->shared->hdf5_eof)); + H5F_addr_inc(&(f->shared->hdf5_eof), p - buf); + H5F_low_seteof(f->shared->lf, &(f->shared->hdf5_eof)); } + /* write the boot block to disk */ - if (H5F_low_write(f->shared->lf, &(f->shared->boot_addr), p - buf, buf) < 0) { - HRETURN_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "can't write header"); + if (H5F_low_write(f->shared->lf, &(f->shared->access_parms), + &(f->shared->boot_addr), p-buf, buf)<0) { + HRETURN_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "can't write header"); } + /* Flush file buffers to disk */ - if (H5F_low_flush(f->shared->lf) < 0) { - HRETURN_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "low level flush failed"); + if (H5F_low_flush(f->shared->lf, &(f->shared->access_parms)) < 0) { + HRETURN_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "low level flush failed"); } FUNC_LEAVE(SUCCEED); } /*------------------------------------------------------------------------- - * Function: H5F_close + * Function: H5F_close * - * Purpose: Closes an open HDF5 file. + * Purpose: Closes an open HDF5 file. * - * Return: Success: SUCCEED + * Return: Success: SUCCEED * - * Failure: FAIL + * Failure: FAIL * - * Programmer: Robb Matzke - * Tuesday, September 23, 1997 + * Programmer: Robb Matzke + * Tuesday, September 23, 1997 * * Modifications: * @@ -1287,13 +1312,13 @@ H5F_close(H5F_t *f) FUNC_ENTER(H5F_close, FAIL); /* Close all current working groups */ - while (H5G_pop(f) >= 0) /*void */ - ; + while (H5G_pop(f) >= 0) /*void*/; /* Flush the boot block and caches */ if (H5F_flush(f, TRUE) < 0) { - HRETURN_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "can't flush cache"); + HRETURN_ERROR(H5E_CACHE, H5E_CANTFLUSH, FAIL, "can't flush cache"); } + /* * If object headers are still open then delay deletion of resources until * they have all been closed. The file is in a consistent state now, so @@ -1301,25 +1326,25 @@ H5F_close(H5F_t *f) */ if (f->nopen > 0) { #ifndef NDEBUG - fprintf(stderr, "HDF5-DIAG: H5F_close: %d object header%s still " - "open (file close will complete when %s closed)\n", - f->nopen, - 1 == f->nopen ? " is" : "s are", - 1 == f->nopen ? "that header is" : "those headers are"); + fprintf(stderr, "HDF5-DIAG: H5F_close: %d object header%s still " + "open (file close will complete when %s closed)\n", + f->nopen, + 1 == f->nopen ? " is" : "s are", + 1 == f->nopen ? "that header is" : "those headers are"); #endif - f->close_pending = TRUE; - HRETURN(SUCCEED); + f->close_pending = TRUE; + HRETURN(SUCCEED); } else if (f->close_pending) { #ifndef NDEBUG - fprintf(stderr, "HDF5-DIAG: H5F_close: operation completed\n"); + fprintf(stderr, "HDF5-DIAG: H5F_close: operation completed\n"); #endif } + /* Dump debugging info */ - if (f->intent & H5F_ACC_DEBUG) - H5AC_debug(f); + if (f->intent & H5F_ACC_DEBUG) H5AC_debug(f); /* Close files and release resources */ - H5F_low_close(f->shared->lf); + H5F_low_close(f->shared->lf, &(f->shared->access_parms)); f = H5F_dest(f); FUNC_LEAVE(SUCCEED); @@ -1335,19 +1360,19 @@ H5F_close(H5F_t *f) USAGE herr_t H5Fclose(fid) - int32 fid; IN: File ID of file to close + int32 fid; IN: File ID of file to close ERRORS - ARGS BADTYPE Not a file atom. - ATOM BADATOM Can't remove atom. - ATOM BADATOM Can't unatomize file. - CACHE CANTFLUSH Can't flush cache. + ARGS BADTYPE Not a file atom. + ATOM BADATOM Can't remove atom. + ATOM BADATOM Can't unatomize file. + CACHE CANTFLUSH Can't flush cache. RETURNS SUCCEED/FAIL DESCRIPTION - This function terminates access to an HDF5 file. If this is the last + 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. @@ -1362,45 +1387,48 @@ H5F_close(H5F_t *f) herr_t H5Fclose(hid_t fid) { - H5F_t *file = NULL; /* file struct for file to close */ - herr_t ret_value = SUCCEED; + H5F_t *file = NULL; /* file struct for file to close */ + herr_t ret_value = SUCCEED; FUNC_ENTER(H5Fclose, FAIL); /* Check/fix arguments. */ - if (H5_FILE != H5A_group(fid)) - HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file atom"); - if (NULL == (file = H5A_object(fid))) - HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "can't unatomize file"); + if (H5_FILE != H5A_group(fid)) { + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a file atom"); + } + if (NULL == (file = H5A_object(fid))) { + HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "can't unatomize file"); + } /* Close the file */ ret_value = H5F_close(file); /* Remove the file atom */ if (NULL == H5A_remove(fid)) { - HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "can't remove atom"); + HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "can't remove atom"); } - done: + + done: FUNC_LEAVE(ret_value < 0 ? FAIL : SUCCEED); } /*------------------------------------------------------------------------- - * Function: H5F_block_read + * Function: H5F_block_read * - * Purpose: Reads some data from a file/server/etc into a buffer. - * The data is contiguous. The address is relative to the base - * address for the file. + * Purpose: Reads some data from a file/server/etc into a buffer. + * The data is contiguous. The address is relative to the base + * address for the file. * * Errors: - * IO READERROR Low-level read failed. + * IO READERROR Low-level read failed. * - * Return: Success: SUCCEED + * Return: Success: SUCCEED * - * Failure: FAIL + * Failure: FAIL * - * Programmer: Robb Matzke - * matzke@llnl.gov - * Jul 10 1997 + * Programmer: Robb Matzke + * matzke@llnl.gov + * Jul 10 1997 * * Modifications: * @@ -1409,42 +1437,43 @@ H5Fclose(hid_t fid) herr_t H5F_block_read(H5F_t *f, const haddr_t *addr, size_t size, void *buf) { - haddr_t abs_addr; + haddr_t abs_addr; FUNC_ENTER(H5F_block_read, FAIL); if (0 == size) - return 0; + return 0; /* convert the relative address to an absolute address */ abs_addr = f->shared->base_addr; H5F_addr_add(&abs_addr, addr); /* Read the data */ - if (H5F_low_read(f->shared->lf, &abs_addr, size, buf) < 0) { - HRETURN_ERROR(H5E_IO, H5E_READERROR, FAIL, "low-level read failed"); + if (H5F_low_read(f->shared->lf, &(f->shared->access_parms), + &abs_addr, size, buf) < 0) { + HRETURN_ERROR(H5E_IO, H5E_READERROR, FAIL, "low-level read failed"); } FUNC_LEAVE(SUCCEED); } /*------------------------------------------------------------------------- - * Function: H5F_block_write + * Function: H5F_block_write * - * Purpose: Writes some data from memory to a file/server/etc. The - * data is contiguous. The address is relative to the base - * address. + * Purpose: Writes some data from memory to a file/server/etc. The + * data is contiguous. The address is relative to the base + * address. * * Errors: - * IO WRITEERROR Low-level write failed. - * IO WRITEERROR No write intent. + * IO WRITEERROR Low-level write failed. + * IO WRITEERROR No write intent. * - * Return: Success: SUCCEED + * Return: Success: SUCCEED * - * Failure: FAIL + * Failure: FAIL * - * Programmer: Robb Matzke - * matzke@llnl.gov - * Jul 10 1997 + * Programmer: Robb Matzke + * matzke@llnl.gov + * Jul 10 1997 * * Modifications: * @@ -1453,43 +1482,46 @@ H5F_block_read(H5F_t *f, const haddr_t *addr, size_t size, void *buf) herr_t H5F_block_write(H5F_t *f, const haddr_t *addr, size_t size, const void *buf) { - haddr_t abs_addr; + haddr_t abs_addr; FUNC_ENTER(H5F_block_write, FAIL); if (0 == size) - return 0; + return 0; - if (0 == (f->intent & H5F_ACC_WRITE)) { - HRETURN_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "no write intent"); + if (0 == (f->intent & H5F_ACC_RDWR)) { + HRETURN_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "no write intent"); } + /* Convert the relative address to an absolute address */ abs_addr = f->shared->base_addr; H5F_addr_add(&abs_addr, addr); /* Write the data */ - if (H5F_low_write(f->shared->lf, &abs_addr, size, buf)) { - HRETURN_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "low-level write failed"); + if (H5F_low_write(f->shared->lf, &(f->shared->access_parms), + &abs_addr, size, buf)) { + HRETURN_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "low-level write failed"); } + FUNC_LEAVE(SUCCEED); } /*------------------------------------------------------------------------- - * Function: H5F_debug + * Function: H5F_debug * - * Purpose: Prints a file header to the specified stream. Each line - * is indented and the field name occupies the specified width - * number of characters. + * Purpose: Prints a file header to the specified stream. Each line + * is indented and the field name occupies the specified width + * number of characters. * * Errors: * - * Return: Success: SUCCEED + * Return: Success: SUCCEED * - * Failure: FAIL + * Failure: FAIL * - * Programmer: Robb Matzke - * matzke@llnl.gov - * Aug 1 1997 + * Programmer: Robb Matzke + * matzke@llnl.gov + * Aug 1 1997 * * Modifications: * @@ -1497,7 +1529,7 @@ H5F_block_write(H5F_t *f, const haddr_t *addr, size_t size, const void *buf) */ herr_t H5F_debug(H5F_t *f, const haddr_t *addr, FILE * stream, intn indent, - intn fwidth) + intn fwidth) { FUNC_ENTER(H5F_debug, FAIL); @@ -1512,80 +1544,80 @@ H5F_debug(H5F_t *f, const haddr_t *addr, FILE * stream, intn indent, fprintf(stream, "%*sFile Boot Block...\n", indent, ""); fprintf(stream, "%*s%-*s %s\n", indent, "", fwidth, - "File name:", - f->name); + "File name:", + f->name); fprintf(stream, "%*s%-*s 0x%08x\n", indent, "", fwidth, - "Flags", - (unsigned) (f->shared->flags)); + "Flags", + (unsigned) (f->shared->flags)); fprintf(stream, "%*s%-*s %u\n", indent, "", fwidth, - "Reference count:", - (unsigned) (f->shared->nrefs)); + "Reference count:", + (unsigned) (f->shared->nrefs)); fprintf(stream, "%*s%-*s 0x%08lx\n", indent, "", fwidth, - "Consistency flags:", - (unsigned long) (f->shared->consist_flags)); + "Consistency flags:", + (unsigned long) (f->shared->consist_flags)); fprintf(stream, "%*s%-*s ", indent, "", fwidth, - "Address of boot block:"); + "Address of boot block:"); H5F_addr_print(stream, &(f->shared->boot_addr)); fprintf(stream, " (abs)\n"); fprintf(stream, "%*s%-*s ", indent, "", fwidth, - "Base address:"); + "Base address:"); H5F_addr_print(stream, &(f->shared->base_addr)); fprintf(stream, " (abs)\n"); fprintf(stream, "%*s%-*s ", indent, "", fwidth, - "Small object heap address:"); + "Small object heap address:"); H5F_addr_print(stream, &(f->shared->smallobj_addr)); fprintf(stream, " (rel)\n"); fprintf(stream, "%*s%-*s ", indent, "", fwidth, - "Free list address:"); + "Free list address:"); H5F_addr_print(stream, &(f->shared->freespace_addr)); fprintf(stream, " (rel)\n"); fprintf(stream, "%*s%-*s ", indent, "", fwidth, - "Total size of hdf5 data:"); + "Total size of hdf5 data:"); H5F_addr_print(stream, &(f->shared->hdf5_eof)); fprintf(stream, " bytes\n"); fprintf(stream, "%*s%-*s %lu bytes\n", indent, "", fwidth, - "Size of user block:", - (unsigned long) (f->shared->create_parms.userblock_size)); + "Size of user block:", + (unsigned long) (f->shared->create_parms.userblock_size)); fprintf(stream, "%*s%-*s %u bytes\n", indent, "", fwidth, - "Size of file size_t type:", - (unsigned) (f->shared->create_parms.sizeof_size)); + "Size of file size_t type:", + (unsigned) (f->shared->create_parms.sizeof_size)); fprintf(stream, "%*s%-*s %u bytes\n", indent, "", fwidth, - "Size of file haddr_t type:", - (unsigned) (f->shared->create_parms.sizeof_addr)); + "Size of file haddr_t type:", + (unsigned) (f->shared->create_parms.sizeof_addr)); fprintf(stream, "%*s%-*s %u\n", indent, "", fwidth, - "Symbol table leaf node 1/2 rank:", - (unsigned) (f->shared->create_parms.sym_leaf_k)); + "Symbol table leaf node 1/2 rank:", + (unsigned) (f->shared->create_parms.sym_leaf_k)); fprintf(stream, "%*s%-*s %u\n", indent, "", fwidth, - "Symbol table internal node 1/2 rank:", - (unsigned) (f->shared->create_parms.btree_k[H5B_SNODE_ID])); + "Symbol table internal node 1/2 rank:", + (unsigned) (f->shared->create_parms.btree_k[H5B_SNODE_ID])); fprintf(stream, "%*s%-*s %u\n", indent, "", fwidth, - "Boot block version number:", - (unsigned) (f->shared->create_parms.bootblock_ver)); + "Boot block version number:", + (unsigned) (f->shared->create_parms.bootblock_ver)); fprintf(stream, "%*s%-*s %u\n", indent, "", fwidth, - "Small object heap version number:", - (unsigned) (f->shared->create_parms.smallobject_ver)); + "Small object heap version number:", + (unsigned) (f->shared->create_parms.smallobject_ver)); fprintf(stream, "%*s%-*s %u\n", indent, "", fwidth, - "Free list version number:", - (unsigned) (f->shared->create_parms.freespace_ver)); + "Free list version number:", + (unsigned) (f->shared->create_parms.freespace_ver)); fprintf(stream, "%*s%-*s %u\n", indent, "", fwidth, - "Object directory version number:", - (unsigned) (f->shared->create_parms.objectdir_ver)); + "Object directory version number:", + (unsigned) (f->shared->create_parms.objectdir_ver)); fprintf(stream, "%*s%-*s %u\n", indent, "", fwidth, - "Shared header version number:", - (unsigned) (f->shared->create_parms.sharedheader_ver)); + "Shared header version number:", + (unsigned) (f->shared->create_parms.sharedheader_ver)); fprintf(stream, "%*s%-*s %s\n", indent, "", fwidth, - "Root symbol table entry:", - f->shared->root_ent ? "" : "(none)"); + "Root symbol table entry:", + f->shared->root_ent ? "" : "(none)"); if (f->shared->root_ent) { - H5G_ent_debug(f, f->shared->root_ent, stream, - indent + 3, MAX(0, fwidth - 3)); + H5G_ent_debug(f, f->shared->root_ent, stream, + indent + 3, MAX(0, fwidth - 3)); } FUNC_LEAVE(SUCCEED); } diff --git a/src/H5Fcore.c b/src/H5Fcore.c index 9069df5..d274422 100644 --- a/src/H5Fcore.c +++ b/src/H5Fcore.c @@ -19,32 +19,35 @@ #include <H5Fprivate.h> #include <H5MMprivate.h> -#define H5F_CORE_INC 10240 /*amount by which to grow file */ #define H5F_CORE_DEV 0xffff /*pseudo dev for core until we fix things */ #define PABLO_MASK H5F_core static hbool_t interface_initialize_g = FALSE; #define INTERFACE_INIT NULL -static hbool_t H5F_core_access(const char *name, int mode, H5F_search_t *key); -static H5F_low_t *H5F_core_open(const char *name, uintn flags, H5F_search_t *); -static herr_t H5F_core_close(H5F_low_t *lf); -static herr_t H5F_core_read(H5F_low_t *lf, const haddr_t *addr, size_t size, - uint8 *buf); -static herr_t H5F_core_write(H5F_low_t *lf, const haddr_t *addr, size_t size, - const uint8 *buf); +static hbool_t H5F_core_access(const char *name, + const H5F_access_t *access_parms, int mode, + H5F_search_t *key/*out*/); +static H5F_low_t *H5F_core_open(const char *name, + const H5F_access_t *access_parms, uintn flags, + H5F_search_t *key/*out*/); +static herr_t H5F_core_close(H5F_low_t *lf, const H5F_access_t *access_parms); +static herr_t H5F_core_read(H5F_low_t *lf, const H5F_access_t *access_parms, + const haddr_t *addr, size_t size, uint8 *buf); +static herr_t H5F_core_write(H5F_low_t *lf, const H5F_access_t *access_parms, + const haddr_t *addr, size_t size, + const uint8 *buf); + +const H5F_low_class_t H5F_LOW_CORE_g[1] = {{ + H5F_core_access, /* access method */ + H5F_core_open, /* open method */ + H5F_core_close, /* close method */ + H5F_core_read, /* read method */ + H5F_core_write, /* write method */ + NULL, /* flush method */ + NULL, /* extend method */ +}}; -const H5F_low_class_t H5F_LOW_CORE[1] = -{ - { - H5F_core_access, /* access method */ - H5F_core_open, /* open method */ - H5F_core_close, /* close method */ - H5F_core_read, /* read method */ - H5F_core_write, /* write method */ - NULL, /* flush method */ - NULL, /* extend method */ - }}; /*------------------------------------------------------------------------- * Function: H5F_core_access @@ -66,11 +69,13 @@ const H5F_low_class_t H5F_LOW_CORE[1] = *------------------------------------------------------------------------- */ static hbool_t -H5F_core_access(const char *name, int mode, H5F_search_t *key /*out */ ) +H5F_core_access(const char *name, const H5F_access_t *access_parms, + int mode, H5F_search_t *key/*out*/) { FUNC_ENTER(H5F_core_access, FAIL); FUNC_LEAVE(FALSE); } + /*------------------------------------------------------------------------- * Function: H5F_core_open @@ -93,21 +98,23 @@ H5F_core_access(const char *name, int mode, H5F_search_t *key /*out */ ) * *------------------------------------------------------------------------- */ -static H5F_low_t * -H5F_core_open(const char *name, uintn flags, H5F_search_t *key) +static H5F_low_t * +H5F_core_open(const char *name, const H5F_access_t *access_parms, + uintn flags, H5F_search_t *key/*out*/) { H5F_low_t *lf = NULL; static ino_t ino = 0; FUNC_ENTER(H5F_core_open, NULL); - if (0 == (flags & H5F_ACC_WRITE) || 0 == (flags & H5F_ACC_CREAT)) { + if (0 == (flags & H5F_ACC_RDWR) || 0 == (flags & H5F_ACC_CREAT)) { HRETURN_ERROR(H5E_IO, H5E_CANTOPENFILE, NULL, "must creat file with write access"); } + lf = H5MM_xcalloc(1, sizeof(H5F_low_t)); - lf->u.core.mem = H5MM_xmalloc(H5F_CORE_INC); - lf->u.core.alloc = H5F_CORE_INC; + lf->u.core.mem = NULL; + lf->u.core.alloc = 0; lf->u.core.size = 0; H5F_addr_reset(&(lf->eof)); @@ -115,8 +122,10 @@ H5F_core_open(const char *name, uintn flags, H5F_search_t *key) key->dev = H5F_CORE_DEV; key->ino = ino++; } + FUNC_LEAVE(lf); } + /*------------------------------------------------------------------------- * Function: H5F_core_close @@ -137,7 +146,7 @@ H5F_core_open(const char *name, uintn flags, H5F_search_t *key) *------------------------------------------------------------------------- */ static herr_t -H5F_core_close(H5F_low_t *lf) +H5F_core_close(H5F_low_t *lf, const H5F_access_t *access_parms) { FUNC_ENTER(H5F_core_close, FAIL); @@ -147,6 +156,7 @@ H5F_core_close(H5F_low_t *lf) FUNC_LEAVE(SUCCEED); } + /*------------------------------------------------------------------------- * Function: H5F_core_read @@ -169,7 +179,8 @@ H5F_core_close(H5F_low_t *lf) *------------------------------------------------------------------------- */ static herr_t -H5F_core_read(H5F_low_t *lf, const haddr_t *addr, size_t size, uint8 *buf) +H5F_core_read(H5F_low_t *lf, const H5F_access_t *access_parms, + const haddr_t *addr, size_t size, uint8 *buf) { size_t n; size_t eof; @@ -192,6 +203,7 @@ H5F_core_read(H5F_low_t *lf, const haddr_t *addr, size_t size, uint8 *buf) FUNC_LEAVE(SUCCEED); } + /*------------------------------------------------------------------------- * Function: H5F_core_write @@ -214,27 +226,39 @@ H5F_core_read(H5F_low_t *lf, const haddr_t *addr, size_t size, uint8 *buf) *------------------------------------------------------------------------- */ static herr_t -H5F_core_write(H5F_low_t *lf, const haddr_t *addr, size_t size, - const uint8 *buf) +H5F_core_write(H5F_low_t *lf, const H5F_access_t *access_parms, + const haddr_t *addr, size_t size, const uint8 *buf) { - size_t inc_amount; + size_t need_more; + size_t increment = 1; + FUNC_ENTER(H5F_core_write, FAIL); assert(lf); assert(addr && H5F_addr_defined(addr)); assert(buf); + assert (!access_parms || H5F_LOW_CORE==access_parms->driver); - /* Allocate more space */ + /* + * Allocate more space. We always allocate a multiple of the increment + * size, which is either defined in the file access property list or + * which defaults to one. + */ if (addr->offset + size > lf->u.core.alloc) { - inc_amount = MAX(addr->offset + size - lf->u.core.alloc, H5F_CORE_INC); - lf->u.core.alloc = lf->u.core.alloc + inc_amount; + if (access_parms) increment = access_parms->u.core.increment; + need_more = addr->offset+size - lf->u.core.alloc; + need_more = increment*((need_more+increment-1)/increment); + + lf->u.core.alloc = lf->u.core.alloc + need_more; lf->u.core.mem = H5MM_xrealloc(lf->u.core.mem, lf->u.core.alloc); } + /* Move the physical EOF marker */ if (addr->offset + size > lf->u.core.size) { lf->u.core.size = addr->offset + size; } + /* Copy data */ HDmemcpy(lf->u.core.mem + addr->offset, buf, size); diff --git a/src/H5Ffamily.c b/src/H5Ffamily.c index 025039c..dba22f1 100644 --- a/src/H5Ffamily.c +++ b/src/H5Ffamily.c @@ -1,25 +1,25 @@ /* * Copyright (C) 1997 Spizella Software - * All rights reserved. + * All rights reserved. * * Programmer: Robb Matzke <matzke@llnl.gov> - * Monday, November 10, 1997 - * - * Purpose: Implements a family of files that acts as a single hdf5 - * file. The purpose is to be able to split a huge file on a - * 64-bit platform, transfer all the <2GB members to a 32-bit - * platform, and then access the entire huge file on the 32-bit - * platform. - * - * All family members are logically the same size although their - * physical sizes may vary. The logical member size is - * determined by looking at the physical size of the first - * member and rounding that up to the next power of two. When - * creating a file family, the first member is created with a - * predefined physical size (actually, this happens when the - * file family is flushed, and can be quite time consuming on - * file systems that don't implement holes, like nfs). - * + * Monday, November 10, 1997 + * + * Purpose: Implements a family of files that acts as a single hdf5 + * file. The purpose is to be able to split a huge file on a + * 64-bit platform, transfer all the <2GB members to a 32-bit + * platform, and then access the entire huge file on the 32-bit + * platform. + * + * All family members are logically the same size although their + * physical sizes may vary. The logical member size is + * determined by looking at the physical size of the first + * member and rounding that up to the next power of two. When + * creating a file family, the first member is created with a + * predefined physical size (actually, this happens when the + * file family is flushed, and can be quite time consuming on + * file systems that don't implement holes, like nfs). + * */ #include <H5private.h> #include <H5Eprivate.h> @@ -27,7 +27,7 @@ #include <H5MMprivate.h> #define PABLO_MASK H5F_family -static hbool_t interface_initialize_g = FALSE; +static hbool_t interface_initialize_g = FALSE; #define INTERFACE_INIT NULL /* @@ -38,81 +38,104 @@ static hbool_t interface_initialize_g = FALSE; * Smaller values result in files of a more manageable size (from a human * perspective) but also limit the total logical size of the hdf5 file. */ -#define H5F_FAM_DFLT_NBITS 26u /*64MB */ - -#define H5F_FAM_MASK(N) (((uint64)1<<(N))-1) -#define H5F_FAM_OFFSET(ADDR,N) ((off_t)((ADDR)->offset & H5F_FAM_MASK(N))) -#define H5F_FAM_MEMBNO(ADDR,N) ((intn)((ADDR)->offset >> N)) - -static hbool_t H5F_fam_access(const char *name, int mode, H5F_search_t *key); -static H5F_low_t *H5F_fam_open(const char *name, uintn flags, H5F_search_t *); -static herr_t H5F_fam_close(H5F_low_t *lf); -static herr_t H5F_fam_read(H5F_low_t *lf, const haddr_t *addr, size_t size, - uint8 *buf); -static herr_t H5F_fam_write(H5F_low_t *lf, const haddr_t *addr, size_t size, +#define H5F_FAM_DFLT_NBITS 26u /*64MB */ + +#define H5F_FAM_MASK(N) (((uint64)1<<(N))-1) +#define H5F_FAM_OFFSET(ADDR,N) ((off_t)((ADDR)->offset & H5F_FAM_MASK(N))) +#define H5F_FAM_MEMBNO(ADDR,N) ((intn)((ADDR)->offset >> N)) + +static hbool_t H5F_fam_access(const char *name, + const H5F_access_t *access_parms, int mode, + H5F_search_t *key/*out*/); +static H5F_low_t *H5F_fam_open(const char *name, + const H5F_access_t *access_parms, uintn flags, + H5F_search_t *key/*out*/); +static herr_t H5F_fam_close(H5F_low_t *lf, const H5F_access_t *access_parms); +static herr_t H5F_fam_read(H5F_low_t *lf, const H5F_access_t *access_parms, + const haddr_t *addr, size_t size, uint8 *buf); +static herr_t H5F_fam_write(H5F_low_t *lf, const H5F_access_t *access_parms, + const haddr_t *addr, size_t size, const uint8 *buf); -static herr_t H5F_fam_flush(H5F_low_t *lf); - -const H5F_low_class_t H5F_LOW_FAM[1] = {{ - H5F_fam_access, /* access method */ - H5F_fam_open, /* open method */ - H5F_fam_close, /* close method */ - H5F_fam_read, /* read method */ - H5F_fam_write, /* write method */ - H5F_fam_flush, /* flush method */ - NULL, /* extend method */ +static herr_t H5F_fam_flush(H5F_low_t *lf, const H5F_access_t *access_parms); + +const H5F_low_class_t H5F_LOW_FAMILY_g[1] = {{ + H5F_fam_access, /* access method */ + H5F_fam_open, /* open method */ + H5F_fam_close, /* close method */ + H5F_fam_read, /* read method */ + H5F_fam_write, /* write method */ + H5F_fam_flush, /* flush method */ + NULL, /* extend method */ }}; /*------------------------------------------------------------------------- - * Function: H5F_fam_open + * Function: H5F_fam_open * - * Purpose: Opens a file family with the specified base name. The name - * should contain a printf-style "%d" field which will be - * expanded with a zero-origin family member number. + * Purpose: Opens a file family with the specified base name. The name + * should contain a printf-style "%d" field which will be + * expanded with a zero-origin family member number. * - * Bugs: We don't check for overflow on the name, so keep it under - * 4kb, please. Also, we don't actually check for the `%d' - * field because we assume that the caller already did. Who - * knows what happens when all the family member names are the - * same! + * Bugs: We don't check for overflow on the name, so keep it under + * 4kb, please. Also, we don't actually check for the `%d' + * field because we assume that the caller already did. Who + * knows what happens when all the family member names are the + * same! * - * Return: Success: Low-level file pointer + * Return: Success: Low-level file pointer * - * Failure: NULL + * Failure: NULL * - * Programmer: Robb Matzke - * Monday, November 10, 1997 + * Programmer: Robb Matzke + * Monday, November 10, 1997 * * Modifications: * *------------------------------------------------------------------------- */ -static H5F_low_t * -H5F_fam_open(const char *name, uintn flags, H5F_search_t *key /*out */ ) +static H5F_low_t * +H5F_fam_open(const char *name, const H5F_access_t *access_parms, + uintn flags, H5F_search_t *key/*out*/) { - H5F_low_t *ret_value = NULL, *lf = NULL; - H5F_low_t *member = NULL; /*a family member */ - char member_name[4096]; /*name of family member */ - intn membno; /*member number (zero-origin) */ - size_t nbits = H5F_FAM_DFLT_NBITS; /*num bits in an offset */ - haddr_t tmp_addr; /*temporary address */ + H5F_low_t *ret_value = NULL; + H5F_low_t *lf = NULL; + H5F_low_t *member = NULL; /*a family member */ + char member_name[4096]; /*name of family member */ + intn membno; /*member number (zero-origin) */ + size_t nbits = H5F_FAM_DFLT_NBITS; /*num bits in an offset */ + haddr_t tmp_addr; /*temporary address */ + const H5F_low_class_t *memb_type; /*type of family member */ FUNC_ENTER(H5F_fam_open, NULL); + assert (access_parms); + assert (H5F_LOW_FAMILY==access_parms->driver); + + /* + * Use the default file driver or the specified driver for each of the + * family members. + */ + if (access_parms->u.fam.memb_access) { + memb_type = H5F_low_class (access_parms->u.fam.memb_access->driver); + } else { + memb_type = H5F_low_class (H5F_LOW_DFLT); + } + /* * If we're truncating the file then delete all but the first family - * member. Use the default number of bits for the offset. + * member. Use the default number of bits for the offset. */ - if ((flags & H5F_ACC_WRITE) && (flags & H5F_ACC_TRUNC)) { - for (membno = 1; /*void */ ; membno++) { - sprintf(member_name, name, membno); - if (!H5F_low_access(H5F_LOW_DFLT, member_name, F_OK, NULL)) { - break; - } else if (unlink(member_name) < 0) { - HGOTO_ERROR(H5E_IO, H5E_CANTINIT, NULL, "can't delete member"); - } - } + if ((flags & H5F_ACC_RDWR) && (flags & H5F_ACC_TRUNC)) { + for (membno = 1; /*void*/; membno++) { + sprintf(member_name, name, membno); + if (!H5F_low_access(memb_type, member_name, + access_parms->u.fam.memb_access, + F_OK, NULL)) { + break; + } else if (unlink(member_name) < 0) { + HGOTO_ERROR(H5E_IO, H5E_CANTINIT, NULL, "can't delete member"); + } + } } /* Create the file descriptor */ lf = H5MM_xcalloc(1, sizeof(H5F_low_t)); @@ -120,33 +143,34 @@ H5F_fam_open(const char *name, uintn flags, H5F_search_t *key /*out */ ) lf->u.fam.flags = (flags & ~H5F_ACC_CREAT); /* Open all existing members */ - for (membno = 0; /*void */ ; membno++) { - sprintf(member_name, name, membno); - - /* - * Open the family member. After the first member is opened or created, - * turn off the creation flag so we don't create a zillion family - * members. - */ - member = H5F_low_open(H5F_LOW_DFLT, member_name, flags, - 0 == membno ? key : NULL); - if (!member) { - if (0 == membno) { - HGOTO_ERROR(H5E_IO, H5E_CANTOPENFILE, NULL, - "can't open first family member"); - } - break; - } - flags &= ~H5F_ACC_CREAT; - - /* Add the member to the family */ - if (lf->u.fam.nmemb >= lf->u.fam.nalloc) { - lf->u.fam.nalloc = MAX(100, 2 * lf->u.fam.nalloc); - lf->u.fam.memb = H5MM_xrealloc(lf->u.fam.memb, - lf->u.fam.nalloc * sizeof(H5F_low_t *)); - } - lf->u.fam.memb[lf->u.fam.nmemb++] = member; - member = NULL; + for (membno = 0; /*void*/; membno++) { + sprintf(member_name, name, membno); + + /* + * Open the family member. After the first member is opened or + * created, turn off the creation flag so we don't create a zillion + * family members. + */ + member = H5F_low_open(memb_type, member_name, + access_parms->u.fam.memb_access, flags, + 0 == membno ? key : NULL); + if (!member) { + if (0 == membno) { + HGOTO_ERROR(H5E_IO, H5E_CANTOPENFILE, NULL, + "can't open first family member"); + } + break; + } + flags &= ~H5F_ACC_CREAT; + + /* Add the member to the family */ + if (lf->u.fam.nmemb >= lf->u.fam.nalloc) { + lf->u.fam.nalloc = MAX(100, 2 * lf->u.fam.nalloc); + lf->u.fam.memb = H5MM_xrealloc(lf->u.fam.memb, + lf->u.fam.nalloc * sizeof(H5F_low_t *)); + } + lf->u.fam.memb[lf->u.fam.nmemb++] = member; + member = NULL; } /* @@ -155,32 +179,36 @@ H5F_fam_open(const char *name, uintn flags, H5F_search_t *key /*out */ ) * member. */ if (lf->u.fam.nmemb >= 2) { - size_t size = H5F_low_size(lf->u.fam.memb[0], &tmp_addr); - for (nbits = 8 * sizeof(size_t) - 1; nbits > 0; --nbits) { - size_t mask = (size_t) 1 << nbits; - if (size & mask) { - if (size != mask) { - size++; + size_t size = H5F_low_size(lf->u.fam.memb[0], &tmp_addr); + for (nbits=8*sizeof(size_t)-1; nbits>0; --nbits) { + size_t mask = (size_t)1 << nbits; + if (size & mask) { + if (size != mask) { + size++; #ifdef H5F_DEBUG - fprintf(stderr, "HDF5-DIAG: family member size was rounded up " - "to a power of 2"); + fprintf(stderr, "HDF5-DIAG: family member size was rounded up " + "to a power of 2"); #endif - } - break; - } - } + } + break; + } + } } lf->u.fam.offset_bits = nbits; #ifdef H5F_DEBUG if (nbits >= 30) { - fprintf(stderr, "HDF5-DIAG: family members are %dGB\n", 1 << (nbits - 30)); + fprintf(stderr, "HDF5-DIAG: family members are %dGB\n", + 1 << (nbits-30)); } else if (nbits >= 20) { - fprintf(stderr, "HDF5-DIAG: family members are %dMB\n", 1 << (nbits - 20)); + fprintf(stderr, "HDF5-DIAG: family members are %dMB\n", + 1 << (nbits-20)); } else if (nbits >= 10) { - fprintf(stderr, "HDF5-DIAG: family members are %dkB\n", 1 << (nbits - 10)); + fprintf(stderr, "HDF5-DIAG: family members are %dkB\n", + 1 << (nbits-10)); } else { - fprintf(stderr, "HDF5-DIAG: family members are %d bytes\n", 1 << nbits); + fprintf(stderr, "HDF5-DIAG: family members are %d bytes\n", + 1 << nbits); } #endif @@ -188,50 +216,51 @@ H5F_fam_open(const char *name, uintn flags, H5F_search_t *key /*out */ ) * Get the total family size and store it in the max_addr field. */ assert(lf->u.fam.nmemb >= 1); - lf->eof.offset = (size_t) 1 << lf->u.fam.offset_bits; - lf->eof.offset *= (lf->u.fam.nmemb - 1); - lf->eof.offset += lf->u.fam.memb[lf->u.fam.nmemb - 1]->eof.offset; + lf->eof.offset = (size_t)1 << lf->u.fam.offset_bits; + lf->eof.offset *= (lf->u.fam.nmemb-1); + lf->eof.offset += lf->u.fam.memb[lf->u.fam.nmemb-1]->eof.offset; HRETURN(lf); done: if (!ret_value) { - if (lf) { - H5F_fam_close(lf); - H5MM_xfree(lf); - } + if (lf) { + H5F_fam_close(lf, access_parms); + H5MM_xfree(lf); + } } FUNC_LEAVE(ret_value); } /*------------------------------------------------------------------------- - * Function: H5F_fam_close + * Function: H5F_fam_close * - * Purpose: Closes all members of a file family and releases resources - * used by the file descriptor. + * Purpose: Closes all members of a file family and releases resources + * used by the file descriptor. * - * Return: Success: SUCCEED + * Return: Success: SUCCEED * - * Failure: FAIL + * Failure: FAIL * - * Programmer: Robb Matzke - * Monday, November 10, 1997 + * Programmer: Robb Matzke + * Monday, November 10, 1997 * * Modifications: * *------------------------------------------------------------------------- */ static herr_t -H5F_fam_close(H5F_low_t *lf) +H5F_fam_close(H5F_low_t *lf, const H5F_access_t *access_parms) { - intn membno; + intn membno; FUNC_ENTER(H5F_fam_close, FAIL); assert(lf); for (membno = 0; membno < lf->u.fam.nmemb; membno++) { - lf->u.fam.memb[membno] = H5F_low_close(lf->u.fam.memb[membno]); + lf->u.fam.memb[membno] = H5F_low_close(lf->u.fam.memb[membno], + access_parms->u.fam.memb_access); } H5MM_xfree(lf->u.fam.memb); H5MM_xfree(lf->u.fam.name); @@ -240,36 +269,37 @@ H5F_fam_close(H5F_low_t *lf) } /*------------------------------------------------------------------------- - * Function: H5F_fam_read + * Function: H5F_fam_read * - * Purpose: Reads a chunk of contiguous data from the file family. - * Reading past the physical end of a file returns zeros instead - * of failing. We must insure that if the logical end of file is - * before the physical end of file that we will read zeros there - * also (the only time this can happen is if we create a family - * and then close it before the first member is filled, since - * flushing the file causes the first member to be physically - * extended to it's maximum size). + * Purpose: Reads a chunk of contiguous data from the file family. + * Reading past the physical end of a file returns zeros instead + * of failing. We must insure that if the logical end of file is + * before the physical end of file that we will read zeros there + * also (the only time this can happen is if we create a family + * and then close it before the first member is filled, since + * flushing the file causes the first member to be physically + * extended to it's maximum size). * - * Return: Success: SUCCEED + * Return: Success: SUCCEED * - * Failure: FAIL + * Failure: FAIL * - * Programmer: Robb Matzke - * Monday, November 10, 1997 + * Programmer: Robb Matzke + * Monday, November 10, 1997 * * Modifications: * *------------------------------------------------------------------------- */ static herr_t -H5F_fam_read(H5F_low_t *lf, const haddr_t *addr, size_t size, uint8 *buf) +H5F_fam_read(H5F_low_t *lf, const H5F_access_t *access_parms, + const haddr_t *addr, size_t size, uint8 *buf) { - size_t nbytes; - haddr_t cur_addr; - uintn membno; - off_t offset; - size_t member_size; + size_t nbytes; + haddr_t cur_addr; + uintn membno; + off_t offset; + size_t member_size; FUNC_ENTER(H5F_fam_read, FAIL); @@ -283,154 +313,168 @@ H5F_fam_read(H5F_low_t *lf, const haddr_t *addr, size_t size, uint8 *buf) cur_addr = *addr; while (size > 0) { - if (membno >= lf->u.fam.nmemb) { - HDmemset(buf, 0, size); - break; - } else { - nbytes = MIN(size, member_size - offset); - cur_addr.offset = offset; - if (H5F_low_read(lf->u.fam.memb[membno], &cur_addr, - nbytes, buf) < 0) { - HRETURN_ERROR(H5E_IO, H5E_READERROR, FAIL, - "can't read from family member"); - } - buf += nbytes; - size -= nbytes; - membno++; - offset = 0; - } + if (membno >= lf->u.fam.nmemb) { + HDmemset(buf, 0, size); + break; + } else { + nbytes = MIN(size, member_size - offset); + cur_addr.offset = offset; + if (H5F_low_read(lf->u.fam.memb[membno], + access_parms->u.fam.memb_access, + &cur_addr, nbytes, buf) < 0) { + HRETURN_ERROR(H5E_IO, H5E_READERROR, FAIL, + "can't read from family member"); + } + buf += nbytes; + size -= nbytes; + membno++; + offset = 0; + } } FUNC_LEAVE(SUCCEED); } /*------------------------------------------------------------------------- - * Function: H5F_fam_write + * Function: H5F_fam_write * - * Purpose: Writes BUF to the family of files. The superclass has - * already insured that we aren't writing past the logical end - * of file, so this function will extend the physical file to - * accommodate the new data if necessary. + * Purpose: Writes BUF to the family of files. The superclass has + * already insured that we aren't writing past the logical end + * of file, so this function will extend the physical file to + * accommodate the new data if necessary. * - * Return: Success: SUCCEED + * Return: Success: SUCCEED * - * Failure: FAIL + * Failure: FAIL * - * Programmer: Robb Matzke - * Monday, November 10, 1997 + * Programmer: Robb Matzke + * Monday, November 10, 1997 * * Modifications: * *------------------------------------------------------------------------- */ static herr_t -H5F_fam_write(H5F_low_t *lf, const haddr_t *addr, size_t size, - const uint8 *buf) +H5F_fam_write(H5F_low_t *lf, const H5F_access_t *access_parms, + const haddr_t *addr, size_t size, const uint8 *buf) { - size_t nbytes; - haddr_t cur_addr, max_addr; - uintn membno; - off_t offset; - H5F_low_t *member = NULL; - char member_name[4096]; - intn i; - size_t member_size; - + size_t nbytes; + haddr_t cur_addr, max_addr; + uintn membno; + off_t offset; + H5F_low_t *member = NULL; + char member_name[4096]; + intn i; + size_t member_size; + const H5F_low_class_t *memb_type = NULL; + FUNC_ENTER(H5F_fam_write, FAIL); + /* Check args */ assert(lf); assert(addr && H5F_addr_defined(addr)); assert(buf); + assert (access_parms); + assert (H5F_LOW_FAMILY==access_parms->driver); + /* Get the member driver */ + if (access_parms->u.fam.memb_access) { + memb_type = H5F_low_class (access_parms->u.fam.memb_access->driver); + } else { + memb_type = H5F_low_class (H5F_LOW_DFLT); + } + member_size = (size_t) 1 << lf->u.fam.offset_bits; membno = H5F_FAM_MEMBNO(addr, lf->u.fam.offset_bits); offset = H5F_FAM_OFFSET(addr, lf->u.fam.offset_bits); cur_addr = *addr; while (size > 0) { - nbytes = MIN(size, member_size - offset); - cur_addr.offset = offset; - - if (membno >= lf->u.fam.nmemb) { - /* - * We're writing past the end of the last family member--create the - * new family member(s) - */ - for (i = lf->u.fam.nmemb; i <= membno; i++) { - sprintf(member_name, lf->u.fam.name, i); - member = H5F_low_open(H5F_LOW_DFLT, member_name, - lf->u.fam.flags | H5F_ACC_CREAT, - NULL); - if (!member) { - HRETURN_ERROR(H5E_IO, H5E_CANTOPENFILE, FAIL, - "can't create a new member"); - } - /* - * For members in the middle, set their logical eof to the - * maximum possible value. - */ - if (i < membno) { - H5F_addr_reset(&max_addr); - H5F_addr_inc(&max_addr, member_size); - H5F_low_seteof(member, &max_addr); - } - if (lf->u.fam.nmemb >= lf->u.fam.nalloc) { - lf->u.fam.nalloc *= 2; - lf->u.fam.memb = H5MM_xrealloc(lf->u.fam.memb, - (lf->u.fam.nalloc * - sizeof(H5F_low_t *))); - } - lf->u.fam.memb[lf->u.fam.nmemb++] = member; - } - } - /* - * Make sure the logical eof is large enough to handle the request. - */ - max_addr = cur_addr; - H5F_addr_inc(&max_addr, nbytes); - H5F_low_seteof(lf->u.fam.memb[membno], &max_addr); - - /* Write the data to the member */ - if (H5F_low_write(lf->u.fam.memb[membno], &cur_addr, - nbytes, buf) < 0) { - HRETURN_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, - "can't write to family member"); - } - buf += nbytes; - size -= nbytes; - membno++; - offset = 0; + nbytes = MIN(size, member_size - offset); + cur_addr.offset = offset; + + if (membno >= lf->u.fam.nmemb) { + /* + * We're writing past the end of the last family member--create the + * new family member(s) + */ + for (i = lf->u.fam.nmemb; i <= membno; i++) { + sprintf(member_name, lf->u.fam.name, i); + member = H5F_low_open(memb_type, member_name, + access_parms->u.fam.memb_access, + lf->u.fam.flags | H5F_ACC_CREAT, + NULL); + if (!member) { + HRETURN_ERROR(H5E_IO, H5E_CANTOPENFILE, FAIL, + "can't create a new member"); + } + /* + * For members in the middle, set their logical eof to the + * maximum possible value. + */ + if (i < membno) { + H5F_addr_reset(&max_addr); + H5F_addr_inc(&max_addr, member_size); + H5F_low_seteof(member, &max_addr); + } + if (lf->u.fam.nmemb >= lf->u.fam.nalloc) { + lf->u.fam.nalloc *= 2; + lf->u.fam.memb = H5MM_xrealloc(lf->u.fam.memb, + (lf->u.fam.nalloc * + sizeof(H5F_low_t *))); + } + lf->u.fam.memb[lf->u.fam.nmemb++] = member; + } + } + /* + * Make sure the logical eof is large enough to handle the request. + */ + max_addr = cur_addr; + H5F_addr_inc(&max_addr, nbytes); + H5F_low_seteof(lf->u.fam.memb[membno], &max_addr); + + /* Write the data to the member */ + if (H5F_low_write(lf->u.fam.memb[membno], + access_parms->u.fam.memb_access, + &cur_addr, nbytes, buf) < 0) { + HRETURN_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, + "can't write to family member"); + } + buf += nbytes; + size -= nbytes; + membno++; + offset = 0; } FUNC_LEAVE(SUCCEED); } /*------------------------------------------------------------------------- - * Function: H5F_fam_flush + * Function: H5F_fam_flush * - * Purpose: Flushes all data to disk and makes sure that the first member - * is as large as a member can be so we can accurately detect - * the member size if we open this file for read access at a - * later date. + * Purpose: Flushes all data to disk and makes sure that the first member + * is as large as a member can be so we can accurately detect + * the member size if we open this file for read access at a + * later date. * - * Return: Success: SUCCEED + * Return: Success: SUCCEED * - * Failure: FAIL + * Failure: FAIL * - * Programmer: Robb Matzke - * Monday, November 10, 1997 + * Programmer: Robb Matzke + * Monday, November 10, 1997 * * Modifications: * *------------------------------------------------------------------------- */ static herr_t -H5F_fam_flush(H5F_low_t *lf) +H5F_fam_flush(H5F_low_t *lf, const H5F_access_t *access_parms) { - int membno, nerrors = 0; - uint8 buf[1]; - haddr_t addr1, addr2, addr3; - size_t max_offset; + int membno, nerrors = 0; + uint8 buf[1]; + haddr_t addr1, addr2, addr3; + size_t max_offset; FUNC_ENTER(H5F_fam_flush, FAIL); @@ -444,98 +488,118 @@ H5F_fam_flush(H5F_low_t *lf) max_offset = H5F_FAM_MASK(lf->u.fam.offset_bits); H5F_addr_reset(&addr1); H5F_addr_inc(&addr1, max_offset); - H5F_low_size(lf->u.fam.memb[0], &addr2); /*remember logical eof */ + H5F_low_size(lf->u.fam.memb[0], &addr2); /*remember logical eof */ addr3 = addr1; H5F_addr_inc(&addr3, (size_t) 1); - H5F_low_seteof(lf->u.fam.memb[0], &addr3); /*prevent a warning */ - if (H5F_low_read(lf->u.fam.memb[0], &addr1, 1, buf) < 0) { - HRETURN_ERROR(H5E_IO, H5E_READERROR, FAIL, - "can't read from first family member"); + H5F_low_seteof(lf->u.fam.memb[0], &addr3); /*prevent a warning */ + if (H5F_low_read(lf->u.fam.memb[0], access_parms->u.fam.memb_access, + &addr1, 1, buf) < 0) { + HRETURN_ERROR(H5E_IO, H5E_READERROR, FAIL, + "can't read from first family member"); } - if (H5F_low_write(lf->u.fam.memb[0], &addr1, 1, buf) < 0) { - HRETURN_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, - "can't write to first family member"); + if (H5F_low_write(lf->u.fam.memb[0], access_parms->u.fam.memb_access, + &addr1, 1, buf) < 0) { + HRETURN_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, + "can't write to first family member"); } - H5F_low_seteof(lf->u.fam.memb[0], &addr2); /*reset old eof */ + H5F_low_seteof(lf->u.fam.memb[0], &addr2); /*reset old eof */ /* - * Flush each member file. Don't return an error status until we've + * Flush each member file. Don't return an error status until we've * flushed as much as possible. */ for (membno = 0; membno < lf->u.fam.nmemb; membno++) { - if (H5F_low_flush(lf->u.fam.memb[membno]) < 0) { - nerrors++; - } + if (H5F_low_flush(lf->u.fam.memb[membno], + access_parms->u.fam.memb_access) < 0) { + nerrors++; + } } if (nerrors) { - HRETURN_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, - "can't flush family member"); + HRETURN_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, + "can't flush family member"); } FUNC_LEAVE(SUCCEED); } /*------------------------------------------------------------------------- - * Function: H5F_fam_access + * Function: H5F_fam_access * - * Purpose: Determines if all members of the file family can be accessed - * and returns the key for the first member of the family. + * Purpose: Determines if all members of the file family can be accessed + * and returns the key for the first member of the family. * - * Return: Success: TRUE or FALSE + * Return: Success: TRUE or FALSE * - * Failure: FAIL + * Failure: FAIL * - * Programmer: Robb Matzke - * Monday, November 10, 1997 + * Programmer: Robb Matzke + * Monday, November 10, 1997 * * Modifications: * *------------------------------------------------------------------------- */ static hbool_t -H5F_fam_access(const char *name, int mode, H5F_search_t *key /*out */ ) +H5F_fam_access(const char *name, const H5F_access_t *access_parms, + int mode, H5F_search_t *key/*out*/) { - intn membno; - char member_name[4096]; - hbool_t status; - hbool_t ret_value = FALSE; + intn membno; + char member_name[4096]; + hbool_t status; + hbool_t ret_value = FALSE; + const H5F_low_class_t *memb_type = NULL; FUNC_ENTER(H5F_fam_access, FAIL); + /* Check args */ + assert (name && *name); + assert (access_parms); + assert (H5F_LOW_FAMILY==access_parms->driver); + + /* Get the driver for the family members */ + if (access_parms->u.fam.memb_access) { + memb_type = H5F_low_class (access_parms->u.fam.memb_access->driver); + } else { + memb_type = H5F_low_class (H5F_LOW_DFLT); + } + + /* Access the members */ for (membno=0; /*void*/; membno++) { - sprintf(member_name, name, membno); - status = H5F_low_access(H5F_LOW_DFLT, member_name, mode, - 0 == membno ? key : NULL); - - if (!status) { - if (F_OK == mode) { - /* - * If we didn't find a member then we must have gotten to the end - * of the family. As long as we found the first member(s) the - * family exists. - */ - ret_value = membno > 0 ? TRUE : FALSE; + sprintf(member_name, name, membno); + status = H5F_low_access(memb_type, member_name, NULL, mode, + 0 == membno ? key : NULL); + + if (!status) { + if (F_OK == mode) { + /* + * If we didn't find a member then we must have gotten to the + * end of the family. As long as we found the first + * member(s) the family exists. + */ + ret_value = membno > 0 ? TRUE : FALSE; break; - } else if (H5F_low_access(H5F_LOW_DFLT, member_name, F_OK, NULL)) { - /* - * The file exists but didn't have the write access permissions. - */ + } else if (H5F_low_access(memb_type, member_name, + access_parms->u.fam.memb_access, + F_OK, NULL)) { + /* + * The file exists but didn't have the write access permissions. + */ ret_value = FALSE; break; - } else { - /* - * The file doesn't exist because we got to the end of the - * family. - */ + } else { + /* + * The file doesn't exist because we got to the end of the + * family. + */ ret_value = TRUE; break; - } - } - if (status < 0) { - HRETURN_ERROR(H5E_IO, H5E_CANTOPENFILE, FAIL, - "access method failed for a member file"); - } + } + } + if (status < 0) { + HRETURN_ERROR(H5E_IO, H5E_CANTOPENFILE, FAIL, + "access method failed for a member file"); + } } FUNC_LEAVE(ret_value); diff --git a/src/H5Flow.c b/src/H5Flow.c index edafc1f..6455571 100644 --- a/src/H5Flow.c +++ b/src/H5Flow.c @@ -23,6 +23,67 @@ #define PABLO_MASK H5F_low static hbool_t interface_initialize_g = FALSE; #define INTERFACE_INIT NULL + + +/*------------------------------------------------------------------------- + * Function: H5F_low_class + * + * Purpose: Given a driver identifier return the class pointer for that + * low-level driver. + * + * Return: Success: A low-level driver class pointer. + * + * Failure: NULL + * + * Programmer: Robb Matzke + * Wednesday, February 18, 1998 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +const H5F_low_class_t * +H5F_low_class (H5F_driver_t driver) +{ + const H5F_low_class_t *type = NULL; + + FUNC_ENTER (H5F_low_class, NULL); + + switch (driver) { + case H5F_LOW_STDIO: + type = H5F_LOW_STDIO_g; + break; + + case H5F_LOW_SEC2: + type = H5F_LOW_SEC2_g; + break; + + case H5F_LOW_CORE: + type = H5F_LOW_CORE_g; + break; + +#ifdef HAVE_PARALLEL + case H5F_LOW_MPIO: + type = H5F_LOW_MPIO_g; + break; +#endif + + case H5F_LOW_SPLIT: + type = H5F_LOW_SPLIT_g; + break; + + case H5F_LOW_FAMILY: + type = H5F_LOW_FAMILY_g; + break; + + default: + HRETURN_ERROR (H5E_IO, H5E_UNSUPPORTED, NULL, + "unknown low-level driver"); + } + + FUNC_LEAVE (type); +} + /*------------------------------------------------------------------------- * Function: H5F_low_open @@ -67,9 +128,10 @@ static hbool_t interface_initialize_g = FALSE; * *------------------------------------------------------------------------- */ -H5F_low_t * -H5F_low_open(const H5F_low_class_t *type, const char *name, uintn flags, - H5F_search_t *key /*out */ ) +H5F_low_t * +H5F_low_open(const H5F_low_class_t *type, const char *name, + const H5F_access_t *access_parms, uintn flags, + H5F_search_t *key/*out*/) { H5F_low_t *lf = NULL; @@ -78,7 +140,7 @@ H5F_low_open(const H5F_low_class_t *type, const char *name, uintn flags, assert(type && type->open); assert(name && *name); - if (NULL == (lf = (type->open) (name, flags, key))) { + if (NULL == (lf = (type->open) (name, access_parms, flags, key))) { HRETURN_ERROR(H5E_IO, H5E_CANTOPENFILE, NULL, "open failed"); } lf->type = type; @@ -114,13 +176,13 @@ H5F_low_open(const H5F_low_class_t *type, const char *name, uintn flags, * *------------------------------------------------------------------------- */ -H5F_low_t * -H5F_low_close(H5F_low_t *lf) +H5F_low_t * +H5F_low_close(H5F_low_t *lf, const H5F_access_t *access_parms) { FUNC_ENTER(H5F_low_close, NULL); if (lf) { - if ((lf->type->close) (lf) < 0) { + if ((lf->type->close) (lf, access_parms) < 0) { H5MM_xfree(lf); HRETURN_ERROR(H5E_IO, H5E_CLOSEERROR, NULL, "close failed"); } @@ -156,8 +218,8 @@ H5F_low_close(H5F_low_t *lf) *------------------------------------------------------------------------- */ herr_t -H5F_low_read(H5F_low_t *lf, const haddr_t *addr, size_t size, - uint8 *buf /*out */ ) +H5F_low_read(H5F_low_t *lf, const H5F_access_t *access_parms, + const haddr_t *addr, size_t size, uint8 *buf/*out*/) { herr_t ret_value = FAIL; @@ -168,7 +230,8 @@ H5F_low_read(H5F_low_t *lf, const haddr_t *addr, size_t size, assert(buf); if (lf->type->read) { - if ((ret_value = (lf->type->read) (lf, addr, size, buf)) < 0) { + if ((ret_value = (lf->type->read) (lf, access_parms, addr, size, + buf)) < 0) { HRETURN_ERROR(H5E_IO, H5E_READERROR, ret_value, "read failed"); } } else { @@ -204,8 +267,8 @@ H5F_low_read(H5F_low_t *lf, const haddr_t *addr, size_t size, *------------------------------------------------------------------------- */ herr_t -H5F_low_write(H5F_low_t *lf, const haddr_t *addr, size_t size, - const uint8 *buf) +H5F_low_write(H5F_low_t *lf, const H5F_access_t *access_parms, + const haddr_t *addr, size_t size, const uint8 *buf) { herr_t ret_value = FAIL; haddr_t tmp_addr; @@ -225,7 +288,8 @@ H5F_low_write(H5F_low_t *lf, const haddr_t *addr, size_t size, } /* Write the data */ if (lf->type->write) { - if ((ret_value = (lf->type->write) (lf, addr, size, buf)) < 0) { + if ((ret_value = (lf->type->write) (lf, access_parms, addr, size, + buf)) < 0) { HRETURN_ERROR(H5E_IO, H5E_WRITEERROR, ret_value, "write failed"); } } else { @@ -260,7 +324,7 @@ H5F_low_write(H5F_low_t *lf, const haddr_t *addr, size_t size, *------------------------------------------------------------------------- */ herr_t -H5F_low_flush(H5F_low_t *lf) +H5F_low_flush(H5F_low_t *lf, const H5F_access_t *access_parms) { haddr_t last_byte; uint8 buf[1]; @@ -274,13 +338,13 @@ H5F_low_flush(H5F_low_t *lf) if (addr_defined(&(lf->eof)) && H5F_addr_gt(&(lf->eof), &last_byte)) { last_byte = lf->eof; last_byte.offset -= 1; - if (H5F_low_read(lf, &last_byte, 1, buf) >= 0) { - H5F_low_write(lf, &last_byte, 1, buf); + if (H5F_low_read(lf, access_parms, &last_byte, 1, buf) >= 0) { + H5F_low_write(lf, access_parms, &last_byte, 1, buf); } } /* Invoke the subclass the flush method */ if (lf->type->flush) { - if ((lf->type->flush) (lf) < 0) { + if ((lf->type->flush) (lf, access_parms) < 0) { HRETURN_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "low level flush failed"); } @@ -372,8 +436,9 @@ H5F_low_size(H5F_low_t *lf, haddr_t *eof /*out */ ) *------------------------------------------------------------------------- */ hbool_t -H5F_low_access(const H5F_low_class_t *type, const char *name, int mode, - H5F_search_t *key /*out */ ) +H5F_low_access(const H5F_low_class_t *type, const char *name, + const H5F_access_t *access_parms, int mode, + H5F_search_t *key/*out*/) { hbool_t ret_value; struct stat sb; @@ -382,7 +447,7 @@ H5F_low_access(const H5F_low_class_t *type, const char *name, int mode, assert(type); if (type->access) { - ret_value = (type->access) (name, mode, key /*out */ ); + ret_value = (type->access) (name, access_parms, mode, key /*out*/); } else { ret_value = (0 == access(name, mode) ? TRUE : FALSE); @@ -418,7 +483,8 @@ H5F_low_access(const H5F_low_class_t *type, const char *name, int mode, *------------------------------------------------------------------------- */ herr_t -H5F_low_extend(H5F_low_t *lf, intn op, size_t size, haddr_t *addr /*out */ ) +H5F_low_extend(H5F_low_t *lf, const H5F_access_t *access_parms, intn op, + size_t size, haddr_t *addr/*out*/) { FUNC_ENTER(H5F_low_alloc, FAIL); @@ -427,7 +493,7 @@ H5F_low_extend(H5F_low_t *lf, intn op, size_t size, haddr_t *addr /*out */ ) assert(addr); if (lf->type->extend) { - if ((lf->type->extend) (lf, op, size, addr /*out */ ) < 0) { + if ((lf->type->extend) (lf, access_parms, op, size, addr/*out*/) < 0) { HRETURN_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "unable to extend file"); } diff --git a/src/H5Fmpio.c b/src/H5Fmpio.c index 4c24621..c36500e 100644 --- a/src/H5Fmpio.c +++ b/src/H5Fmpio.c @@ -15,15 +15,16 @@ * and to infer the access flags. If the file is opened, * we close it without reading or writing it. * - It is not possible within MPI-IO to determine whether or not - * the names "file1" and "file2" refer to the same physical fileC + * the names "file1" and "file2" refer to the same physical file * (at least not without writing one and reading the other). * So we do what H5F_core_open() does: return a bogus device * number and a unique inode number. * This has the side effect that calling H5Fopen() twice * with the same name really does open the file twice * and the two handles don't communicate with each other, - * resulting in trashing the file. It also runs the (very small) - * risk of having two unrelated names be seen as the same file. + * resulting in trashing the file. It also runs the (very + * small) risk of having two unrelated names be seen as the + * same file. * * H5F_mpio_open * - should take MPI communicator and MPI info as parameters @@ -57,32 +58,35 @@ static hbool_t interface_initialize_g = FALSE; /* rky??? */ #define H5F_MPIO_DEV 0xfffe /*pseudo dev for MPI-IO until we fix things */ /* Make sure this differs from H5F_CORE_DEV */ -static hbool_t H5F_mpio_access(const char *name, int mode, - H5F_search_t *key /*out */ ); -static H5F_low_t *H5F_mpio_open(const char *name, uintn flags, - H5F_search_t *key); -static herr_t H5F_mpio_close(H5F_low_t *lf); -static herr_t H5F_mpio_read(H5F_low_t *lf, const haddr_t *addr, - size_t size, uint8 *buf); -static herr_t H5F_mpio_write(H5F_low_t *lf, const haddr_t *addr, - size_t size, const uint8 *buf); -static herr_t H5F_mpio_flush(H5F_low_t *lf); -static herr_t H5F_MPIOff_to_haddr( MPI_Offset mpi_off, haddr_t *addr); -static herr_t H5F_haddr_to_MPIOff( haddr_t addr, MPI_Offset *mpi_off); - -const H5F_low_class_t H5F_LOW_MPIO[1] = -{ - { - H5F_mpio_access, /* access method */ - H5F_mpio_open, /* open method */ - H5F_mpio_close, /* close method */ - H5F_mpio_read, /* read method */ - H5F_mpio_write, /* write method */ - H5F_mpio_flush, /* flush method */ - NULL /* extend method */ - }}; +static hbool_t H5F_mpio_access(const char *name, + const H5F_access_t *access_parms, int mode, + H5F_search_t *key/*out*/); +static H5F_low_t *H5F_mpio_open(const char *name, + const H5F_access_t *access_parms, uintn flags, + H5F_search_t *key/*out*/); +static herr_t H5F_mpio_close(H5F_low_t *lf, const H5F_access_t *access_parms); +static herr_t H5F_mpio_read(H5F_low_t *lf, const H5F_access_t *access_parms, + const haddr_t *addr, size_t size, + uint8 *buf/*out*/); +static herr_t H5F_mpio_write(H5F_low_t *lf, const H5F_access_t *access_parms, + const haddr_t *addr, size_t size, + const uint8 *buf); +static herr_t H5F_mpio_flush(H5F_low_t *lf, const H5F_access_t *access_parms); +static herr_t H5F_MPIOff_to_haddr(MPI_Offset mpi_off, haddr_t *addr); +static herr_t H5F_haddr_to_MPIOff(haddr_t addr, MPI_Offset *mpi_off); + +const H5F_low_class_t H5F_LOW_MPIO_g[1] = {{ + H5F_mpio_access, /* access method */ + H5F_mpio_open, /* open method */ + H5F_mpio_close, /* close method */ + H5F_mpio_read, /* read method */ + H5F_mpio_write, /* write method */ + H5F_mpio_flush, /* flush method */ + NULL /* extend method */ +}}; ino_t mpio_inode_num = 0; /* fake "inode" number */ + /*------------------------------------------------------------------------- * Function: H5F_mpio_access @@ -121,10 +125,14 @@ ino_t mpio_inode_num = 0; /* fake "inode" number */ * * Modifications: * + * Robb Matzke, 18 Feb 1998 + * Added the ACCESS_PARMS argument. + * *------------------------------------------------------------------------- */ static hbool_t -H5F_mpio_access(const char *name, int mode, H5F_search_t *key /*out */ ) +H5F_mpio_access(const char *name, const H5F_access_t *access_parms, int mode, + H5F_search_t *key/*out*/) { hbool_t ret_val = FALSE; MPI_File fh; @@ -209,10 +217,15 @@ H5F_mpio_access(const char *name, int mode, H5F_search_t *key /*out */ ) * * Modifications: * + * Robb Matzke, 18 Feb 1998 + * Added the ACCESS_PARMS argument. Moved some error checking here from + * elsewhere. + * *------------------------------------------------------------------------- */ -static H5F_low_t * -H5F_mpio_open(const char *name, uintn flags, H5F_search_t *key /*out */ ) +static H5F_low_t * +H5F_mpio_open(const char *name, const H5F_access_t *access_parms, uintn flags, + H5F_search_t *key/*out*/) { H5F_low_t *lf = NULL; MPI_File fh; @@ -226,9 +239,22 @@ H5F_mpio_open(const char *name, uintn flags, H5F_search_t *key /*out */ ) fprintf(stdout, "Entering H5F_mpio_open name=%s flags=%x\n", name, flags ); #endif + switch (access_parms->u.mpio.access_mode){ + case H5ACC_INDEPENDENT: + /*void*/ + break; + + case H5ACC_COLLECTIVE: + HRETURN_ERROR(H5E_IO, H5E_UNSUPPORTED, NULL, + "collective I/O is not supported yet"); + + default: + HRETURN_ERROR(H5E_IO, H5E_BADVALUE, NULL, "invalid file access mode"); + } + /* convert HDF5 flags to MPI-IO flags */ /* some combinations are illegal; let MPI-IO figure it out */ - mpi_amode = (flags&H5F_ACC_WRITE) ? MPI_MODE_RDWR : MPI_MODE_RDONLY; + mpi_amode = (flags&H5F_ACC_RDWR) ? MPI_MODE_RDWR : MPI_MODE_RDONLY; if (flags&H5F_ACC_CREAT) mpi_amode |= MPI_MODE_CREATE; if (flags&H5F_ACC_EXCL) mpi_amode |= MPI_MODE_EXCL; @@ -303,10 +329,13 @@ H5F_mpio_open(const char *name, uintn flags, H5F_search_t *key /*out */ ) * * Modifications: * + * Robb Matzke, 18 Feb 1998 + * Added the ACCESS_PARMS argument. + * *------------------------------------------------------------------------- */ static herr_t -H5F_mpio_close(H5F_low_t *lf) +H5F_mpio_close(H5F_low_t *lf, const H5F_access_t *access_parms) { int mpierr; char mpierrmsg[MPI_MAX_ERROR_STRING]; @@ -351,10 +380,14 @@ H5F_mpio_close(H5F_low_t *lf) * * Modifications: * + * Robb Matzke, 18 Feb 1998 + * Added the ACCESS_PARMS argument. + * *------------------------------------------------------------------------- */ static herr_t -H5F_mpio_read(H5F_low_t *lf, const haddr_t *addr, size_t size, uint8 *buf) +H5F_mpio_read(H5F_low_t *lf, const H5F_access_t *access_parms, + const haddr_t *addr, size_t size, uint8 *buf/*out*/) { MPI_Offset mpi_off; int size_i, bytes_read, n; @@ -449,11 +482,15 @@ H5F_mpio_read(H5F_low_t *lf, const haddr_t *addr, size_t size, uint8 *buf) * * Modifications: * + * Robb Matzke, 18 Feb 1998 + * Added the ACCESS_PARMS argument. + * *------------------------------------------------------------------------- */ static herr_t -H5F_mpio_write(H5F_low_t *lf, const haddr_t *addr, size_t size, - const uint8 *buf) +H5F_mpio_write(H5F_low_t *lf, const H5F_access_t *access_parms, + const haddr_t *addr, size_t size, + const uint8 *buf) { MPI_Offset mpi_off; MPI_Status mpi_stat; @@ -511,10 +548,13 @@ H5F_mpio_write(H5F_low_t *lf, const haddr_t *addr, size_t size, * * Modifications: * + * Robb Matzke, 18 Feb 1998 + * Added the ACCESS_PARMS argument. + * *------------------------------------------------------------------------- */ static herr_t -H5F_mpio_flush(H5F_low_t *lf) +H5F_mpio_flush(H5F_low_t *lf, const H5F_access_t *access_parms) { int mpierr; char mpierrmsg[MPI_MAX_ERROR_STRING]; diff --git a/src/H5Fprivate.h b/src/H5Fprivate.h index 14c7e72..7daf090 100644 --- a/src/H5Fprivate.h +++ b/src/H5Fprivate.h @@ -53,13 +53,11 @@ #define H5F_SIZEOF_SIZE(F) ((F)->shared->create_parms.sizeof_size) /* - * File open flags. + * Private file open flags. */ -#define H5F_ACC_WRITE 0x0001 /* Open file for read/write access */ -#define H5F_ACC_CREAT 0x0002 /* Create non-existing files */ -#define H5F_ACC_EXCL 0x0004 /* Fail if file exists */ -#define H5F_ACC_TRUNC 0x0008 /* Truncate existing file */ -#define H5F_ACC_DEBUG 0x00010 /* Print debug info */ +#define H5F_ACC_PUBLIC_FLAGS 0x00ff + +#define H5F_ACC_CREAT 0x0100 /* Create non-existing files */ /* * Encode and decode macros for file meta-data. @@ -204,8 +202,10 @@ #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 */ +/* + * 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 } /* @@ -228,11 +228,35 @@ typedef struct H5F_create_t { * File-access template. */ typedef struct H5F_access_t { - uintn access_mode; /* file access mode */ + H5F_driver_t driver; /* Low level file driver */ + union { + + /* Properties for in-core files */ + struct { + size_t increment; /*amount by which to increment size*/ + } core; + + /* Properties for file families */ + struct { + struct H5F_access_t *memb_access; /*plist for the members*/ + } fam; + + /* Properties for the split driver */ + struct { + struct H5F_access_t *meta_access; /*plist for meta file */ + struct H5F_access_t *raw_access; /*plist for raw data file */ + } split; + #ifdef HAVE_PARALLEL - MPI_Comm comm; /* communicator for file access */ - MPI_Info info; /* optional info for MPI-IO */ -#endif /*HAVE_PARALLEL*/ + /* Properties for parallel I/O */ + struct { + uintn access_mode; /* independent or collective variety? */ + MPI_Comm comm; /* communicator for file access */ + MPI_Info info; /* optional info for MPI-IO */ + } mpio; +#endif + + } u; } H5F_access_t; /* @@ -255,18 +279,27 @@ typedef enum { * Define the low-level file interface. */ typedef struct H5F_low_class_t { - hbool_t (*access)(const char *, int, H5F_search_t *); - struct H5F_low_t *(*open)(const char *, uintn, H5F_search_t *); - herr_t (*close)(struct H5F_low_t *); - herr_t (*read)(struct H5F_low_t *, const haddr_t *, size_t, uint8 *); - herr_t (*write)(struct H5F_low_t *, const haddr_t *, size_t, - const uint8 *); - herr_t (*flush)(struct H5F_low_t *); - herr_t (*extend)(struct H5F_low_t *, intn, size_t, haddr_t *); + hbool_t (*access)(const char *name, const H5F_access_t *access_parms, + int mode, H5F_search_t *key/*out*/); + struct H5F_low_t *(*open)(const char *name, + const H5F_access_t *access_parms, uintn flags, + H5F_search_t *key/*out*/); + herr_t (*close)(struct H5F_low_t *lf, + const H5F_access_t *access_parms); + herr_t (*read)(struct H5F_low_t *lf, const H5F_access_t *access_parms, + const haddr_t *addr, size_t size, uint8 *buf); + herr_t (*write)(struct H5F_low_t *lf, + const H5F_access_t *access_parms, + const haddr_t *addr, size_t size, const uint8 *buf); + herr_t (*flush)(struct H5F_low_t *lf, + const H5F_access_t *access_parms); + herr_t (*extend)(struct H5F_low_t *lf, + const H5F_access_t *access_parms, + intn op, size_t size, haddr_t *addr); } H5F_low_class_t; typedef struct H5F_low_t { - const H5F_low_class_t *type; /* What type of file is this? */ + const H5F_low_class_t *type;/* What type of file is this? */ haddr_t eof; /* Address of logical end-of-file */ union { @@ -292,14 +325,22 @@ typedef struct H5F_low_t { struct { int fd; /* The unix file descriptor */ H5F_fileop_t op; /* Previous file operation */ +#ifdef HAVE_LSEEK64 + off64_t cur; /* Current file position */ +#else off_t cur; /* Current file position */ +#endif } sec2; /* Posix stdio */ struct { FILE *f; /* Posix stdio file */ H5F_fileop_t op; /* Previous file operation */ +#ifdef HAVE_FSEEK64 + long long cur; /* Current file position */ +#else off_t cur; /* Current file position */ +#endif } stdio; /* In-core temp file */ @@ -323,13 +364,13 @@ typedef struct H5F_low_t { #ifndef H5F_LOW_DFLT # define H5F_LOW_DFLT H5F_LOW_STDIO /* The default type */ #endif -extern const H5F_low_class_t H5F_LOW_SEC2[]; /* Posix section 2 */ -extern const H5F_low_class_t H5F_LOW_STDIO[]; /* Posix stdio */ -extern const H5F_low_class_t H5F_LOW_CORE[]; /* In-core temp file */ -extern const H5F_low_class_t H5F_LOW_FAM[]; /* File family */ -extern const H5F_low_class_t H5F_LOW_SPLIT[]; /* Split meta/raw data */ +extern const H5F_low_class_t H5F_LOW_SEC2_g[]; /* Posix section 2 */ +extern const H5F_low_class_t H5F_LOW_STDIO_g[]; /* Posix stdio */ +extern const H5F_low_class_t H5F_LOW_CORE_g[]; /* In-core temp file */ +extern const H5F_low_class_t H5F_LOW_FAMILY_g[];/* File family */ +extern const H5F_low_class_t H5F_LOW_SPLIT_g[]; /* Split meta/raw data */ #ifdef HAVE_PARALLEL - extern const H5F_low_class_t H5F_LOW_MPIO[]; /* MPI-IO */ +extern const H5F_low_class_t H5F_LOW_MPIO_g[]; /* MPI-IO */ #endif /* @@ -349,9 +390,7 @@ typedef struct H5F_file_t { haddr_t hdf5_eof; /* Relative addr of end of all hdf5 data*/ struct H5AC_t *cache; /* The object cache */ H5F_create_t create_parms; /* File-creation template */ -#ifdef HAVE_PARALLEL H5F_access_t access_parms; /* File-access template */ -#endif struct H5G_entry_t *root_ent; /* Root symbol table entry */ } H5F_file_t; @@ -411,18 +450,20 @@ struct H5O_layout_t; /*forward decl for prototype arguments */ /* library variables */ extern const H5F_create_t H5F_create_dflt; -extern const H5F_access_t H5F_access_dflt; +extern H5F_access_t H5F_access_dflt; /* Private functions, not part of the publicly documented API */ +herr_t H5F_init_interface(void); void H5F_encode_length_unusual(const H5F_t *f, uint8 **p, uint8 *l); -H5F_t *H5F_open(const H5F_low_class_t *type, const char *name, uintn flags, - const H5F_create_t *create_parms, const H5F_access_t *access_parms); +H5F_t *H5F_open(const char *name, uintn flags, + const H5F_create_t *create_parms, + const H5F_access_t *access_parms); herr_t H5F_close(H5F_t *f); herr_t H5F_debug(H5F_t *f, const haddr_t *addr, FILE * stream, intn indent, intn fwidth); /* Functions that operate on array storage */ -herr_t H5F_arr_create(H5F_t *f, struct H5O_layout_t *layout /*in,out */ ); +herr_t H5F_arr_create(H5F_t *f, struct H5O_layout_t *layout /*in,out*/); herr_t H5F_arr_read (H5F_t *f, const struct H5O_layout_t *layout, const size_t _hslab_size[], const size_t mem_size[], const size_t mem_offset[], const size_t file_offset[], @@ -433,7 +474,7 @@ herr_t H5F_arr_write (H5F_t *f, const struct H5O_layout_t *layout, const void *_buf); /* Functions that operate on indexed storage */ -herr_t H5F_istore_create(H5F_t *f, struct H5O_layout_t *layout /*in,out */ ); +herr_t H5F_istore_create(H5F_t *f, struct H5O_layout_t *layout /*in,out*/); herr_t H5F_istore_read(H5F_t *f, const struct H5O_layout_t *layout, const size_t offset[], const size_t size[], void *buf /*out */ ); @@ -447,19 +488,23 @@ herr_t H5F_block_write(H5F_t *f, const haddr_t *addr, size_t size, const void *buf); /* Functions that operate directly on low-level files */ -herr_t H5F_low_extend(H5F_low_t *lf, intn op, size_t size, haddr_t *addr); +const H5F_low_class_t *H5F_low_class (H5F_driver_t driver); +herr_t H5F_low_extend(H5F_low_t *lf, const H5F_access_t *access_parms, + intn op, size_t size, haddr_t *addr); herr_t H5F_low_seteof(H5F_low_t *lf, const haddr_t *addr); hbool_t H5F_low_access(const H5F_low_class_t *type, const char *name, - int mode, H5F_search_t *key); + const H5F_access_t *access_parms, int mode, + H5F_search_t *key); H5F_low_t *H5F_low_open(const H5F_low_class_t *type, const char *name, - uintn flags, H5F_search_t *key); -H5F_low_t *H5F_low_close(H5F_low_t *lf); + const H5F_access_t *access_parms, uintn flags, + H5F_search_t *key); +H5F_low_t *H5F_low_close(H5F_low_t *lf, const H5F_access_t *access_parms); size_t H5F_low_size(H5F_low_t *lf, haddr_t *addr); -herr_t H5F_low_read(H5F_low_t *lf, const haddr_t *addr, size_t size, - uint8 *buf); -herr_t H5F_low_write(H5F_low_t *lf, const haddr_t *addr, size_t size, - const uint8 *buf); -herr_t H5F_low_flush(H5F_low_t *lf); +herr_t H5F_low_read(H5F_low_t *lf, const H5F_access_t *access_parms, + const haddr_t *addr, size_t size, uint8 *buf); +herr_t H5F_low_write(H5F_low_t *lf, const H5F_access_t *access_parms, + const haddr_t *addr, size_t size, const uint8 *buf); +herr_t H5F_low_flush(H5F_low_t *lf, const H5F_access_t *access_parms); /* Functions that operate on addresses */ #define H5F_addr_eq(A1,A2) (H5F_addr_cmp(A1,A2)==0) diff --git a/src/H5Fpublic.h b/src/H5Fpublic.h index 538b07b..51d4d56 100644 --- a/src/H5Fpublic.h +++ b/src/H5Fpublic.h @@ -20,15 +20,50 @@ #include <H5public.h> #include <H5Apublic.h> -/* file access codes */ -#define H5ACC_DEFAULT 0x0000/*use in H5Fopen & H5Fcreate to open a file with default access*/ -#define H5ACC_WRITE 0x0001/*use in H5Fopen to open a file with write access*/ -#define H5ACC_OVERWRITE 0x0002/*use in H5Fcreate truncate an existing file*/ -#ifdef HAVE_PARALLEL -#define H5ACC_INDEPENDENT 0x0010/*use in H5Cset_mpi for MPI independent access*/ -#define H5ACC_COLLECTIVE 0x0011/*use in H5Cset_mpi for MPI collective access*/ +/* + * These are the bits that can be passed to the `flags' argument of + * H5Fcreate() and H5Fopen(). Use the bit-wise OR operator (|) to combine + * them as needed. + */ +#define H5F_ACC_RDONLY 0x0000 /*absence of write implies read only */ +#define H5F_ACC_RDWR 0x0001 /*open file for reading and writing */ +#define H5F_ACC_TRUNC 0x0002 /*overwrite existing files during create*/ +#define H5F_ACC_EXCL 0x0004 /*create fails if file already exists */ +#define H5F_ACC_DEBUG 0x0008 /*print debug info */ + + +#ifdef LATER +/* + * These are here temporarily for backward compatibility with version + * 5.1.0.0a and should eventually be removed since they violate the naming + * scheme. + */ +#define H5ACC_DEFAULT H5F_ACC_RDONLY +#define H5ACC_WRITE H5F_ACC_RDWR +#define H5ACC_OVERWRITE H5F_ACC_TRUNC #endif +/* + * Low-level file drivers. These values are returned by H5Cget_file_driver() + * and are set by the various H5Cset_...() functions that set file driver + * properties. + */ +typedef enum H5F_driver_t { + H5F_LOW_ERROR = -1, /*error return value */ + H5F_LOW_STDIO = 0, /*use functions declared in stdio.h */ + H5F_LOW_SEC2 = 1, /*use functions declared in unistd.h */ + H5F_LOW_MPIO = 2, /*use indep or collective MPI-IO */ + H5F_LOW_CORE = 3, /*use malloc() and free() */ + H5F_LOW_SPLIT = 4, /*separate meta data from raw data */ + H5F_LOW_FAMILY = 5, /*split addr space over many files */ +} H5F_driver_t; + + +/* Parallel styles passed to H5Cset_mpi() */ +#ifdef HAVE_PARALLEL +# define H5ACC_INDEPENDENT 0x0010 /*MPI independent access */ +# define H5ACC_COLLECTIVE 0x0011 /*MPI collective access */ +#endif #ifdef __cplusplus extern "C" { @@ -41,6 +76,7 @@ hid_t H5Fcreate (const char *filename, uintn flags, hid_t create_template, hid_t H5Fopen (const char *filename, uintn flags, hid_t access_template); herr_t H5Fclose (hid_t fid); hid_t H5Fget_create_template (hid_t fid); +hid_t H5Fget_access_template (hid_t file_id); #ifdef __cplusplus } diff --git a/src/H5Fsec2.c b/src/H5Fsec2.c index 5fb3b08..dd0ab0f 100644 --- a/src/H5Fsec2.c +++ b/src/H5Fsec2.c @@ -1,18 +1,18 @@ /* * Copyright (C) 1997 NCSA - * All rights reserved. + * All rights reserved. * * Programmer: Robb Matzke <matzke@llnl.gov> - * Wednesday, October 22, 1997 + * Wednesday, October 22, 1997 * * Purpose: This is the Posix section-2 I/O subclass of H5Flow. * * Notes: This driver keeps track of its own file position in order to - * minimize the number of calls to lseek(). We assume that - * opening a file sets the current file position to the beginning - * and that read() and write() modify the file position as - * expected when they return successfully (unsuccessful return - * leaves the file position undefined). + * minimize the number of calls to lseek(). We assume that + * opening a file sets the current file position to the beginning + * and that read() and write() modify the file position as + * expected when they return successfully (unsuccessful return + * leaves the file position undefined). */ #include <H5private.h> #include <H5Eprivate.h> @@ -22,66 +22,70 @@ #include <sys/types.h> #include <sys/stat.h> -#define PABLO_MASK H5F_sec2 -static hbool_t interface_initialize_g = FALSE; -#define INTERFACE_INIT NULL +#define PABLO_MASK H5F_sec2 +static hbool_t interface_initialize_g = FALSE; +#define INTERFACE_INIT NULL -static H5F_low_t *H5F_sec2_open(const char *name, uintn flags, H5F_search_t *); -static herr_t H5F_sec2_close(H5F_low_t *lf); -static herr_t H5F_sec2_read(H5F_low_t *lf, const haddr_t *addr, size_t size, - uint8 *buf); -static herr_t H5F_sec2_write(H5F_low_t *lf, const haddr_t *addr, size_t size, - const uint8 *buf); +static H5F_low_t *H5F_sec2_open(const char *name, + const H5F_access_t *access_parms, uintn flags, + H5F_search_t *key/*out*/); +static herr_t H5F_sec2_close(H5F_low_t *lf, const H5F_access_t *access_parms); +static herr_t H5F_sec2_read(H5F_low_t *lf, const H5F_access_t *access_parms, + const haddr_t *addr, size_t size, + uint8 *buf/*out*/); +static herr_t H5F_sec2_write(H5F_low_t *lf, const H5F_access_t *access_parms, + const haddr_t *addr, size_t size, + const uint8 *buf); + +const H5F_low_class_t H5F_LOW_SEC2_g[1] = {{ + NULL, /* access method */ + H5F_sec2_open, /* open method */ + H5F_sec2_close, /* close method */ + H5F_sec2_read, /* read method */ + H5F_sec2_write, /* write method */ + NULL, /* flush method */ + NULL, /* extend method */ +}}; -const H5F_low_class_t H5F_LOW_SEC2[1] = -{ - { - NULL, /* access method */ - H5F_sec2_open, /* open method */ - H5F_sec2_close, /* close method */ - H5F_sec2_read, /* read method */ - H5F_sec2_write, /* write method */ - NULL, /* flush method */ - NULL, /* extend method */ - }}; /*------------------------------------------------------------------------- - * Function: H5F_sec2_open + * Function: H5F_sec2_open * - * Purpose: Opens a file with name NAME. The FLAGS are a bit field with - * the possible values defined in H5F_low_open(). + * Purpose: Opens a file with name NAME. The FLAGS are a bit field with + * the possible values defined in H5F_low_open(). * * Errors: - * IO CANTOPENFILE Open failed. + * IO CANTOPENFILE Open failed. * - * Return: Success: Low-level file pointer + * Return: Success: Low-level file pointer * - * Failure: NULL + * Failure: NULL * - * Programmer: Robb Matzke - * Wednesday, October 22, 1997 + * Programmer: Robb Matzke + * Wednesday, October 22, 1997 * * Modifications: * *------------------------------------------------------------------------- */ -static H5F_low_t * -H5F_sec2_open(const char *name, uintn flags, H5F_search_t *key /*out */ ) +static H5F_low_t * +H5F_sec2_open(const char *name, const H5F_access_t *access_parms, uintn flags, + H5F_search_t *key/*out*/) { - uintn oflags; - H5F_low_t *lf = NULL; - int fd; - struct stat sb; + uintn oflags; + H5F_low_t *lf = NULL; + int fd; + struct stat sb; FUNC_ENTER(H5F_sec2_open, NULL); - oflags = (flags & H5F_ACC_WRITE) ? O_RDWR : O_RDONLY; + oflags = (flags & H5F_ACC_RDWR) ? O_RDWR : O_RDONLY; oflags |= (flags & H5F_ACC_CREAT) ? O_CREAT : 0; oflags |= (flags & H5F_ACC_EXCL) ? O_EXCL : 0; oflags |= (flags & H5F_ACC_TRUNC) ? O_TRUNC : 0; if ((fd = open(name, oflags, 0666)) < 0) { - HRETURN_ERROR(H5E_IO, H5E_CANTOPENFILE, NULL, "open failed"); + HRETURN_ERROR(H5E_IO, H5E_CANTOPENFILE, NULL, "open failed"); } lf = H5MM_xcalloc(1, sizeof(H5F_low_t)); lf->u.sec2.fd = fd; @@ -91,38 +95,38 @@ H5F_sec2_open(const char *name, uintn flags, H5F_search_t *key /*out */ ) lf->eof.offset = sb.st_size; if (key) { - key->dev = sb.st_dev; - key->ino = sb.st_ino; + key->dev = sb.st_dev; + key->ino = sb.st_ino; } FUNC_LEAVE(lf); } /*------------------------------------------------------------------------- - * Function: H5F_sec2_close + * Function: H5F_sec2_close * - * Purpose: Closes a file. + * Purpose: Closes a file. * * Errors: - * IO CLOSEERROR Close failed. + * IO CLOSEERROR Close failed. * - * Return: Success: SUCCEED + * Return: Success: SUCCEED * - * Failure: FAIL + * Failure: FAIL * - * Programmer: Robb Matzke - * Wednesday, October 22, 1997 + * Programmer: Robb Matzke + * Wednesday, October 22, 1997 * * Modifications: * *------------------------------------------------------------------------- */ static herr_t -H5F_sec2_close(H5F_low_t *lf) +H5F_sec2_close(H5F_low_t *lf, const H5F_access_t *access_parms) { FUNC_ENTER(H5F_sec2_close, FAIL); if (close(lf->u.sec2.fd) < 0) { - HRETURN_ERROR(H5E_IO, H5E_CLOSEERROR, FAIL, "close failed"); + HRETURN_ERROR(H5E_IO, H5E_CLOSEERROR, FAIL, "close failed"); } lf->u.sec2.fd = -1; @@ -130,148 +134,181 @@ H5F_sec2_close(H5F_low_t *lf) } /*------------------------------------------------------------------------- - * Function: H5F_sec2_read + * Function: H5F_sec2_read * - * Purpose: Reads SIZE bytes beginning at address ADDR in file LF and - * places them in buffer BUF. Reading past the logical or - * physical end of file returns zeros instead of failing. + * Purpose: Reads SIZE bytes beginning at address ADDR in file LF and + * places them in buffer BUF. Reading past the logical or + * physical end of file returns zeros instead of failing. * * Errors: - * IO READERROR Read failed. - * IO SEEKERROR Lseek failed. + * IO READERROR Read failed. + * IO SEEKERROR Lseek failed. * - * Return: Success: SUCCEED + * Return: Success: SUCCEED * - * Failure: FAIL + * Failure: FAIL * - * Programmer: Robb Matzke - * Wednesday, October 22, 1997 + * Programmer: Robb Matzke + * Wednesday, October 22, 1997 * * Modifications: * *------------------------------------------------------------------------- */ static herr_t -H5F_sec2_read(H5F_low_t *lf, const haddr_t *addr, size_t size, uint8 *buf) +H5F_sec2_read(H5F_low_t *lf, const H5F_access_t *access_parms, + const haddr_t *addr, size_t size, uint8 *buf) { - ssize_t n; - off_t offset; + ssize_t n; + uint64 mask; +#ifdef HAVE_LSEEK64 + off64_t offset; +#else + off_t offset; +#endif FUNC_ENTER(H5F_sec2_read, FAIL); /* Check for overflow */ - offset = addr->offset; /*FIX_ME*/ - assert("address overflowed" && offset == addr->offset); - assert("overflow" && offset + size >= offset); + mask = (uint64)1 << (8*sizeof(offset)-1); + if (addr->offset >= mask || + addr->offset+size < addr->offset || + addr->offset+size >= mask) { + HRETURN_ERROR (H5E_IO, H5E_OVERFLOW, FAIL, "file address overflowed"); + } +#ifdef HAVE_LSEEK64 + offset = (off64_t)(addr->offset); /*checked for overflow*/ +#else + offset = (off_t)(addr->offset); /*checked for overflow*/ +#endif /* Check easy cases */ - if (0 == size) - HRETURN(SUCCEED); + if (0 == size) HRETURN(SUCCEED); if (offset >= lf->eof.offset) { - HDmemset(buf, 0, size); - HRETURN(SUCCEED); + HDmemset(buf, 0, size); + HRETURN(SUCCEED); } + /* * Optimize seeking. If that optimization is disabled then always call * lseek(). */ if (!H5F_OPT_SEEK || - lf->u.sec2.op == H5F_OP_UNKNOWN || - lf->u.sec2.cur != offset) { - if (lseek(lf->u.sec2.fd, offset, SEEK_SET) < 0) { - HRETURN_ERROR(H5E_IO, H5E_SEEKERROR, FAIL, "lseek failed"); - } - lf->u.sec2.cur = offset; + lf->u.sec2.op == H5F_OP_UNKNOWN || + lf->u.sec2.cur != offset) { + if (lseek(lf->u.sec2.fd, offset, SEEK_SET) < 0) { + HRETURN_ERROR(H5E_IO, H5E_SEEKERROR, FAIL, "lseek failed"); + } + lf->u.sec2.cur = offset; } + /* * Read zeros past the logical end of file (physical is handled below) */ if ((size_t) offset + size > lf->eof.offset) { - size_t nbytes = (size_t) offset + size - lf->eof.offset; - HDmemset(buf + size - nbytes, 0, nbytes); - size -= nbytes; + size_t nbytes = (size_t)offset + size - lf->eof.offset; + HDmemset(buf + size - nbytes, 0, nbytes); + size -= nbytes; } + /* * Read the data. If a read error occurs then set the last file operation * to UNKNOWN because the file position isn't guaranteed by Posix. */ if ((n = read(lf->u.sec2.fd, buf, size)) < 0) { - lf->u.sec2.op = H5F_OP_UNKNOWN; - HRETURN_ERROR(H5E_IO, H5E_READERROR, FAIL, "read failed"); + lf->u.sec2.op = H5F_OP_UNKNOWN; + HRETURN_ERROR(H5E_IO, H5E_READERROR, FAIL, "read failed"); } else if (n < size) { - HDmemset(buf + n, 0, size - n); + HDmemset(buf + n, 0, size - n); } + /* - * Update the file position with the number of bytes actually read. This + * Update the file position with the number of bytes actually read. This * might be different than the number requested. */ lf->u.sec2.op = H5F_OP_READ; lf->u.sec2.cur = offset + n; - assert("address overflowed" && lf->u.sec2.cur >= offset); FUNC_LEAVE(SUCCEED); } /*------------------------------------------------------------------------- - * Function: H5F_sec2_write + * Function: H5F_sec2_write * - * Purpose: Writes SIZE bytes from the beginning of BUF into file LF at - * file address ADDR. + * Purpose: Writes SIZE bytes from the beginning of BUF into file LF at + * file address ADDR. * * Errors: - * IO SEEKERROR Lseek failed. - * IO WRITEERROR Write failed. + * IO SEEKERROR Lseek failed. + * IO WRITEERROR Write failed. * - * Return: Success: SUCCEED + * Return: Success: SUCCEED * - * Failure: FAIL + * Failure: FAIL * - * Programmer: Robb Matzke - * Wednesday, October 22, 1997 + * Programmer: Robb Matzke + * Wednesday, October 22, 1997 * * Modifications: * *------------------------------------------------------------------------- */ static herr_t -H5F_sec2_write(H5F_low_t *lf, const haddr_t *addr, size_t size, - const uint8 *buf) +H5F_sec2_write(H5F_low_t *lf, const H5F_access_t *access_parms, + const haddr_t *addr, size_t size, const uint8 *buf) { - off_t offset; + uint64 mask; + ssize_t n; +#ifdef HAVE_LSEEK64 + off64_t offset; +#else + off_t offset; +#endif FUNC_ENTER(H5F_sec2_write, FAIL); /* Check for overflow */ - offset = addr->offset; /*FIX_ME*/ - assert("address overflowed" && offset == addr->offset); - assert("overflow" && offset + size >= offset); + mask = (uint64)1 << (8*sizeof(offset)-1); + if (addr->offset >= mask || + addr->offset+size < addr->offset || + addr->offset+size >= mask) { + HRETURN_ERROR (H5E_IO, H5E_OVERFLOW, FAIL, "file address overflowed"); + } +#ifdef HAVE_LSEEK64 + offset = (off64_t)(addr->offset); /*checked for overflow*/ + n = (off64_t)size; /*checked for overflow*/ +#else + offset = (off_t)(addr->offset); /*checked for overflow*/ + n = (off_t)size; /*checked for overflow*/ +#endif /* * Optimize seeking. If that optimization is disabled then always call * lseek(). */ if (!H5F_OPT_SEEK || - lf->u.sec2.op == H5F_OP_UNKNOWN || - lf->u.sec2.cur != offset) { - if (lseek(lf->u.sec2.fd, offset, SEEK_SET) < 0) { - HRETURN_ERROR(H5E_IO, H5E_SEEKERROR, FAIL, "lseek failed"); - } - lf->u.sec2.cur = offset; + lf->u.sec2.op == H5F_OP_UNKNOWN || + lf->u.sec2.cur != offset) { + if (lseek(lf->u.sec2.fd, offset, SEEK_SET) < 0) { + HRETURN_ERROR(H5E_IO, H5E_SEEKERROR, FAIL, "lseek failed"); + } + lf->u.sec2.cur = offset; } + /* * Write the data to the file. If the write failed then set the * operation back to UNKNOWN since Posix doesn't gurantee its value. */ - if (size != write(lf->u.sec2.fd, buf, size)) { - lf->u.sec2.op = H5F_OP_UNKNOWN; - HRETURN_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "write failed"); + if (n != write(lf->u.sec2.fd, buf, size)) { + lf->u.sec2.op = H5F_OP_UNKNOWN; + HRETURN_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "write failed"); } + /* * Update the file position. */ lf->u.sec2.op = H5F_OP_WRITE; - lf->u.sec2.cur = offset + size; /*FIX_ME*/ - assert("address overflowed" && lf->u.sec2.cur >= offset); + lf->u.sec2.cur = offset + n; FUNC_LEAVE(SUCCEED); } diff --git a/src/H5Fstdio.c b/src/H5Fstdio.c index a7cb096..ed0cdb2 100644 --- a/src/H5Fstdio.c +++ b/src/H5Fstdio.c @@ -1,9 +1,9 @@ /* * Copyright (C) 1997 NCSA - * All rights reserved. + * All rights reserved. * * Programmer: Robb Matzke <matzke@llnl.gov> - * Wednesday, October 22, 1997 + * Wednesday, October 22, 1997 * * Purpose: This is the Posix stdio.h I/O subclass of H5Flow. */ @@ -16,89 +16,92 @@ #include <sys/types.h> #include <sys/stat.h> -#define PABLO_MASK H5F_stdio -static hbool_t interface_initialize_g = FALSE; -#define INTERFACE_INIT NULL +#define PABLO_MASK H5F_stdio +static hbool_t interface_initialize_g = FALSE; +#define INTERFACE_INIT NULL -static H5F_low_t *H5F_stdio_open(const char *name, uintn flags, - H5F_search_t *key); -static herr_t H5F_stdio_close(H5F_low_t *lf); -static herr_t H5F_stdio_read(H5F_low_t *lf, const haddr_t *addr, size_t size, - uint8 *buf); -static herr_t H5F_stdio_write(H5F_low_t *lf, const haddr_t *addr, size_t size, - const uint8 *buf); -static herr_t H5F_stdio_flush(H5F_low_t *lf); +static H5F_low_t *H5F_stdio_open(const char *name, + const H5F_access_t *access_parms, uintn flags, + H5F_search_t *key/*out*/); +static herr_t H5F_stdio_close(H5F_low_t *lf, const H5F_access_t *access_parms); +static herr_t H5F_stdio_read(H5F_low_t *lf, const H5F_access_t *access_parms, + const haddr_t *addr, size_t size, + uint8 *buf/*out*/); +static herr_t H5F_stdio_write(H5F_low_t *lf, const H5F_access_t *access_parms, + const haddr_t *addr, size_t size, + const uint8 *buf); +static herr_t H5F_stdio_flush(H5F_low_t *lf, const H5F_access_t *access_parms); + +const H5F_low_class_t H5F_LOW_STDIO_g[1] = {{ + NULL, /* use default access(2) func */ + H5F_stdio_open, /* open method */ + H5F_stdio_close, /* close method */ + H5F_stdio_read, /* read method */ + H5F_stdio_write, /* write method */ + H5F_stdio_flush, /* flush method */ + NULL, /* extend method */ +}}; -const H5F_low_class_t H5F_LOW_STDIO[1] = -{ - { - NULL, /* use default access(2) func */ - H5F_stdio_open, /* open method */ - H5F_stdio_close, /* close method */ - H5F_stdio_read, /* read method */ - H5F_stdio_write, /* write method */ - H5F_stdio_flush, /* flush method */ - NULL, /* extend method */ - }}; /*------------------------------------------------------------------------- - * Function: H5F_stdio_open + * Function: H5F_stdio_open * - * Purpose: Opens a file with name NAME. The FLAGS are a bit field with - * the possible values defined in H5F_low_open(). + * Purpose: Opens a file with name NAME. The FLAGS are a bit field with + * the possible values defined in H5F_low_open(). * - * Bugs: H5F_ACC_EXCL has a race condition. + * Bugs: H5F_ACC_EXCL has a race condition. * * Errors: - * IO CANTOPENFILE File doesn't exist and CREAT wasn't - * specified. - * IO CANTOPENFILE Fopen failed. - * IO FILEEXISTS File exists but CREAT and EXCL were - * specified. + * IO CANTOPENFILE File doesn't exist and CREAT wasn't + * specified. + * IO CANTOPENFILE Fopen failed. + * IO FILEEXISTS File exists but CREAT and EXCL were + * specified. * - * Return: Success: Low-level file pointer + * Return: Success: Low-level file pointer * - * Failure: NULL + * Failure: NULL * - * Programmer: Robb Matzke - * Wednesday, October 22, 1997 + * Programmer: Robb Matzke + * Wednesday, October 22, 1997 * * Modifications: * *------------------------------------------------------------------------- */ -static H5F_low_t * -H5F_stdio_open(const char *name, uintn flags, H5F_search_t *key /*out */ ) +static H5F_low_t * +H5F_stdio_open(const char *name, const H5F_access_t *access_parms, + uintn flags, H5F_search_t *key/*out*/) { - H5F_low_t *lf = NULL; - FILE *f = NULL; - struct stat sb; + H5F_low_t *lf = NULL; + FILE *f = NULL; + struct stat sb; FUNC_ENTER(H5F_stdio_open, NULL); if (access(name, F_OK) < 0) { - if ((flags & H5F_ACC_CREAT) && (flags & H5F_ACC_WRITE)) { - f = fopen(name, "wb+"); - } else { - HRETURN_ERROR(H5E_IO, H5E_CANTOPENFILE, NULL, - "file doesn't exist and CREAT wasn't specified"); - } + if ((flags & H5F_ACC_CREAT) && (flags & H5F_ACC_RDWR)) { + f = fopen(name, "wb+"); + } else { + HRETURN_ERROR(H5E_IO, H5E_CANTOPENFILE, NULL, + "file doesn't exist and CREAT wasn't specified"); + } } else if ((flags & H5F_ACC_CREAT) && (flags & H5F_ACC_EXCL)) { - HRETURN_ERROR(H5E_IO, H5E_FILEEXISTS, NULL, - "file exists but CREAT and EXCL were specified"); + HRETURN_ERROR(H5E_IO, H5E_FILEEXISTS, NULL, + "file exists but CREAT and EXCL were specified"); - } else if (flags & H5F_ACC_WRITE) { - if (flags & H5F_ACC_TRUNC) - f = fopen(name, "wb+"); - else - f = fopen(name, "rb+"); + } else if (flags & H5F_ACC_RDWR) { + if (flags & H5F_ACC_TRUNC) + f = fopen(name, "wb+"); + else + f = fopen(name, "rb+"); } else { - f = fopen(name, "rb"); + f = fopen(name, "rb"); } if (!f) - HRETURN_ERROR(H5E_IO, H5E_CANTOPENFILE, NULL, "fopen failed"); + HRETURN_ERROR(H5E_IO, H5E_CANTOPENFILE, NULL, "fopen failed"); /* Build the return value */ lf = H5MM_xcalloc(1, sizeof(H5F_low_t)); @@ -107,46 +110,46 @@ H5F_stdio_open(const char *name, uintn flags, H5F_search_t *key /*out */ ) lf->u.stdio.cur = 0; H5F_addr_reset(&(lf->eof)); if (fseek(lf->u.stdio.f, 0, SEEK_END) < 0) { - lf->u.stdio.op = H5F_OP_UNKNOWN; + lf->u.stdio.op = H5F_OP_UNKNOWN; } else { - H5F_addr_inc(&(lf->eof), ftell(lf->u.stdio.f)); + H5F_addr_inc(&(lf->eof), ftell(lf->u.stdio.f)); } /* The unique key */ if (key) { - fstat(fileno(f), &sb); - key->dev = sb.st_dev; - key->ino = sb.st_ino; + fstat(fileno(f), &sb); + key->dev = sb.st_dev; + key->ino = sb.st_ino; } FUNC_LEAVE(lf); } /*------------------------------------------------------------------------- - * Function: H5F_stdio_close + * Function: H5F_stdio_close * - * Purpose: Closes a file. + * Purpose: Closes a file. * * Errors: - * IO CLOSEERROR Fclose failed. + * IO CLOSEERROR Fclose failed. * - * Return: Success: SUCCEED + * Return: Success: SUCCEED * - * Failure: FAIL + * Failure: FAIL * - * Programmer: Robb Matzke - * Wednesday, October 22, 1997 + * Programmer: Robb Matzke + * Wednesday, October 22, 1997 * * Modifications: * *------------------------------------------------------------------------- */ static herr_t -H5F_stdio_close(H5F_low_t *lf) +H5F_stdio_close(H5F_low_t *lf, const H5F_access_t *access_parms) { FUNC_ENTER(H5F_stdio_close, FAIL); if (fclose(lf->u.stdio.f) < 0) { - HRETURN_ERROR(H5E_IO, H5E_CLOSEERROR, FAIL, "fclose failed"); + HRETURN_ERROR(H5E_IO, H5E_CLOSEERROR, FAIL, "fclose failed"); } lf->u.stdio.f = NULL; @@ -154,66 +157,82 @@ H5F_stdio_close(H5F_low_t *lf) } /*------------------------------------------------------------------------- - * Function: H5F_stdio_read + * Function: H5F_stdio_read * - * Purpose: Reads SIZE bytes beginning at address ADDR in file LF and - * places them in buffer BUF. Reading past the logical or - * physical end of file returns zeros instead of failing. + * Purpose: Reads SIZE bytes beginning at address ADDR in file LF and + * places them in buffer BUF. Reading past the logical or + * physical end of file returns zeros instead of failing. * * Errors: - * IO READERROR Fread failed. - * IO SEEKERROR Fseek failed. + * IO READERROR Fread failed. + * IO SEEKERROR Fseek failed. * - * Return: Success: SUCCEED + * Return: Success: SUCCEED * - * Failure: FAIL + * Failure: FAIL * - * Programmer: Robb Matzke - * Wednesday, October 22, 1997 + * Programmer: Robb Matzke + * Wednesday, October 22, 1997 * * Modifications: * *------------------------------------------------------------------------- */ static herr_t -H5F_stdio_read(H5F_low_t *lf, const haddr_t *addr, size_t size, uint8 *buf) +H5F_stdio_read(H5F_low_t *lf, const H5F_access_t *access_parms, + const haddr_t *addr, size_t size, uint8 *buf/*out*/) { - size_t n; - off_t offset; + size_t n; + uint64 mask; +#ifdef HAVE_FSEEK64 + long long offset; +#else + off_t offset; +#endif FUNC_ENTER(H5F_stdio_read, FAIL); /* Check for overflow */ - offset = addr->offset; /*FIX_ME*/ - assert("address overflowed" && offset == addr->offset); - assert("overflow" && offset + size >= offset); + mask = (uint64)1 << (8*sizeof(offset)-1); + if (addr->offset >= mask || + addr->offset + size < addr->offset || + addr->offset+size >= mask) { + HRETURN_ERROR (H5E_IO, H5E_OVERFLOW, FAIL, "file address overflowed"); + } +#ifdef HAVE_FSEEK64 + offset = (long long)(addr->offset); /*checked for overflow*/ +#else + offset = (off_t)(addr->offset); /*checked for overflow*/ +#endif /* Check easy cases */ - if (0 == size) - HRETURN(SUCCEED); + if (0 == size) HRETURN(SUCCEED); if (offset >= lf->eof.offset) { - HDmemset(buf, 0, size); - HRETURN(SUCCEED); + HDmemset(buf, 0, size); + HRETURN(SUCCEED); } + /* * Seek to the correct file position. */ if (!H5F_OPT_SEEK || - lf->u.stdio.op != H5F_OP_READ || - lf->u.stdio.cur != offset) { - if (fseek(lf->u.stdio.f, offset, SEEK_SET) < 0) { - HRETURN_ERROR(H5E_IO, H5E_SEEKERROR, FAIL, "fseek failed"); - } - lf->u.stdio.cur = offset; + lf->u.stdio.op != H5F_OP_READ || + lf->u.stdio.cur != offset) { + if (fseek(lf->u.stdio.f, offset, SEEK_SET) < 0) { + HRETURN_ERROR(H5E_IO, H5E_SEEKERROR, FAIL, "fseek failed"); + } + lf->u.stdio.cur = offset; } + /* * Read zeros past the logical end of file (physical is handled below) */ if ((size_t) offset + size > lf->eof.offset) { - size_t nbytes = (size_t) offset + size - lf->eof.offset; - HDmemset(buf + size - nbytes, 0, nbytes); - size -= nbytes; + size_t nbytes = (size_t) offset + size - lf->eof.offset; + HDmemset(buf + size - nbytes, 0, nbytes); + size -= nbytes; } + /* * Read the data. Since we're reading single-byte values, a partial read * will advance the file position by N. If N is negative or an error @@ -221,102 +240,122 @@ H5F_stdio_read(H5F_low_t *lf, const haddr_t *addr, size_t size, uint8 *buf) */ n = fread(buf, 1, size, lf->u.stdio.f); if (n <= 0 && ferror(lf->u.stdio.f)) { - lf->u.stdio.op = H5F_OP_UNKNOWN; - HRETURN_ERROR(H5E_IO, H5E_READERROR, FAIL, "fread failed"); + lf->u.stdio.op = H5F_OP_UNKNOWN; + HRETURN_ERROR(H5E_IO, H5E_READERROR, FAIL, "fread failed"); } else if (n < size) { - HDmemset(buf + n, 0, size - n); + HDmemset(buf + n, 0, size - n); } + /* * Update the file position data. */ lf->u.stdio.op = H5F_OP_READ; - lf->u.stdio.cur = offset + n; /*FIX_ME*/ + lf->u.stdio.cur = offset + n; FUNC_LEAVE(SUCCEED); } + /*------------------------------------------------------------------------- - * Function: H5F_stdio_write + * Function: H5F_stdio_write * - * Purpose: Writes SIZE bytes from the beginning of BUF into file LF at - * file address ADDR. + * Purpose: Writes SIZE bytes from the beginning of BUF into file LF at + * file address ADDR. * * Errors: - * IO SEEKERROR Fseek failed. - * IO WRITEERROR Fwrite failed. + * IO SEEKERROR Fseek failed. + * IO WRITEERROR Fwrite failed. * - * Return: Success: SUCCEED + * Return: Success: SUCCEED * - * Failure: FAIL + * Failure: FAIL * - * Programmer: Robb Matzke - * Wednesday, October 22, 1997 + * Programmer: Robb Matzke + * Wednesday, October 22, 1997 * * Modifications: * *------------------------------------------------------------------------- */ static herr_t -H5F_stdio_write(H5F_low_t *lf, const haddr_t *addr, size_t size, - const uint8 *buf) +H5F_stdio_write(H5F_low_t *lf, const H5F_access_t *access_parms, + const haddr_t *addr, size_t size, + const uint8 *buf) { - off_t offset; + ssize_t n; + uint64 mask; +#ifdef HAVE_FSEEK64 + long long offset; +#else + off_t offset; +#endif FUNC_ENTER(H5F_stdio_write, FAIL); /* Check for overflow */ - offset = addr->offset; /*FIX_ME*/ - assert("address overflowed" && offset == addr->offset); - assert("overflow" && offset + size >= offset); + mask = (uint64)1 << (8*sizeof(offset)-1); + if (addr->offset >= mask || + addr->offset+size < addr->offset || + addr->offset+size >= mask) { + HRETURN_ERROR (H5E_IO, H5E_OVERFLOW, FAIL, "file address overflowed"); + } +#ifdef HAVE_FSEEK64 + offset = (long long)(addr->offset); /*checked for overflow*/ + n = (long long)size; /*checked for overflow*/ +#else + offset = (long)(addr->offset); /*checked for overflow*/ + n = (off_t)size; /*checked for overflow*/ +#endif /* * Seek to the correct file position. */ if (!H5F_OPT_SEEK || - lf->u.stdio.op != H5F_OP_WRITE || - lf->u.stdio.cur != offset) { - if (fseek(lf->u.stdio.f, offset, SEEK_SET) < 0) { - HRETURN_ERROR(H5E_IO, H5E_SEEKERROR, FAIL, "fseek failed"); - } - lf->u.stdio.cur = offset; + lf->u.stdio.op != H5F_OP_WRITE || + lf->u.stdio.cur != offset) { + if (fseek(lf->u.stdio.f, offset, SEEK_SET) < 0) { + HRETURN_ERROR(H5E_IO, H5E_SEEKERROR, FAIL, "fseek failed"); + } + lf->u.stdio.cur = offset; } /* * Write the buffer. On successful return, the file position will be * advanced by the number of bytes read. Otherwise nobody knows where it * is. */ - if (size != fwrite(buf, 1, size, lf->u.stdio.f)) { - lf->u.stdio.op = H5F_OP_UNKNOWN; - HRETURN_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "fwrite failed"); + if (n != fwrite(buf, 1, size, lf->u.stdio.f)) { + lf->u.stdio.op = H5F_OP_UNKNOWN; + HRETURN_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "fwrite failed"); } /* * Update seek optimizing data. */ lf->u.stdio.op = H5F_OP_WRITE; - lf->u.stdio.cur = offset + size; /*FIX_ME*/ + lf->u.stdio.cur = offset + n; FUNC_LEAVE(SUCCEED); } + /*------------------------------------------------------------------------- - * Function: H5F_stdio_flush + * Function: H5F_stdio_flush * - * Purpose: Makes sure that all data is on disk. + * Purpose: Makes sure that all data is on disk. * * Errors: - * IO WRITEERROR Fflush failed. + * IO WRITEERROR Fflush failed. * - * Return: Success: SUCCEED + * Return: Success: SUCCEED * - * Failure: FAIL + * Failure: FAIL * - * Programmer: Robb Matzke - * Wednesday, October 22, 1997 + * Programmer: Robb Matzke + * Wednesday, October 22, 1997 * * Modifications: * *------------------------------------------------------------------------- */ static herr_t -H5F_stdio_flush(H5F_low_t *lf) +H5F_stdio_flush(H5F_low_t *lf, const H5F_access_t *access_parms) { FUNC_ENTER(H5F_stdio_flush, FAIL); @@ -330,7 +369,7 @@ H5F_stdio_flush(H5F_low_t *lf) * Flush */ if (fflush(lf->u.stdio.f) < 0) { - HRETURN_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "fflush failed"); + HRETURN_ERROR(H5E_IO, H5E_WRITEERROR, FAIL, "fflush failed"); } FUNC_LEAVE(SUCCEED); } @@ -68,7 +68,8 @@ H5MF_alloc(H5F_t *f, intn op, size_t size, haddr_t *addr /*out */ ) * from there. But for now we just allocate more memory from the end of * the file. */ - if (H5F_low_extend(f->shared->lf, op, size, addr /*out */ ) < 0) { + if (H5F_low_extend(f->shared->lf, &(f->shared->access_parms), op, + size, addr/*out*/) < 0) { HRETURN_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "low level mem management failed"); } diff --git a/src/H5config.h.in b/src/H5config.h.in index be212ba..6efe276 100644 --- a/src/H5config.h.in +++ b/src/H5config.h.in @@ -49,6 +49,12 @@ /* The number of bytes in a short. */ #undef SIZEOF_SHORT +/* Define if you have the fseek64 function. */ +#undef HAVE_FSEEK64 + +/* Define if you have the lseek64 function. */ +#undef HAVE_LSEEK64 + /* Define if you have the mpi library (-lmpi). */ #undef HAVE_LIBMPI diff --git a/src/H5private.h b/src/H5private.h index 128f875..88187fd 100644 --- a/src/H5private.h +++ b/src/H5private.h @@ -46,15 +46,6 @@ # include <unistd.h> #endif -#ifdef HAVE_PARALLEL -/* - * MPIO headers - */ -# include <mpi.h> -# include <mpio.h> -#endif - - /* * Pablo support files. */ diff --git a/src/H5public.h b/src/H5public.h index 9d7eee8..ed7933f 100644 --- a/src/H5public.h +++ b/src/H5public.h @@ -19,8 +19,8 @@ #include <H5config.h> /*from configure */ #include <sys/types.h> #ifdef HAVE_PARALLEL -#include <mpi.h> -#include <mpio.h> +# include <mpi.h> +# include <mpio.h> #endif /* |