Files
src_old/src/h5core/h5_openclose.c
T
gsell 0de4641ec5 - introducing types for local and globale IDs and indices
- different structurs for local elements and stored elements in file
- interator for border facets added
2010-11-12 08:23:00 +00:00

539 lines
11 KiB
C

#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <fcntl.h>
#include "h5core/h5_core.h"
#include "h5_core_private.h"
/*!
\ingroup h5_core
\defgroup h5_core_filehandling
*/
/*!
\ingroup h5_core_filehandling
Check whether \c f points to a valid file handle.
\return H5_SUCCESS or error code
*/
h5_err_t
h5_check_filehandle (
h5_file_t* const f /*!< filehandle to check validity of */
) {
if (f == NULL || f->file < 0 || f->u == NULL || f->b == NULL
#ifndef PARALLEL_IO
|| f->t == NULL
#endif
) {
return h5_error (
f,
H5_ERR_BADFD,
"Called with bad filehandle.");
}
return H5_SUCCESS;
}
/*!
Initialize H5Part
*/
static herr_t
h5priv_error_handler (
hid_t estack_id,
void* __f
) {
#pragma unused __f
if (h5_get_debuglevel() >= 5) {
H5Eprint (estack_id, stderr);
}
return 0;
}
/*!
\ingroup h5_private
\internal
Initialize unstructured data internal data structure.
TODO: Move to file "h5u_openclose.c"
\return H5_SUCCESS or error code
*/
static h5_err_t
h5upriv_open_file (
h5_file_t* const f /*!< IN: file handle */
) {
TRY( f->u = (h5u_fdata_t*)h5priv_alloc (f, NULL, sizeof (*f->u)) );
h5u_fdata_t *u = f->u;
u->shape = -1;
u->diskshape = H5S_ALL;
u->memshape = H5S_ALL;
u->viewstart = -1;
u->viewend = -1;
u->viewindexed = 0;
TRY( u->dcreate_prop = h5priv_create_hdf5_property(f, H5P_DATASET_CREATE) );
return H5_SUCCESS;
}
/*!
\ingroup h5_private
\internal
Initialize H5Block internal structure.
TODO: Move to file "h5b_openclose.c"
\return H5_SUCCESS or error code
*/
static h5_err_t
h5bpriv_open_file (
h5_file_t * const f /*!< IN: file handle */
) {
h5b_fdata_t* b;
if ( f->b ) return H5_SUCCESS;
TRY( f->b = (h5b_fdata_t*)h5priv_alloc( f, NULL, sizeof (*f->b)) );
b = f->b;
memset (b, 0, sizeof (*b));
#if defined(PARALLEL_IO)
size_t n = sizeof (struct h5b_partition) / sizeof (h5_int64_t);
TRY( h5priv_mpi_type_contiguous(f,
n, MPI_LONG_LONG, &b->partition_mpi_t) );
#endif
memset (b->user_layout, 0, sizeof(*b->user_layout));
memset (b->write_layout, 0, sizeof(*b->write_layout));
b->shape = -1;
b->diskshape = -1;
b->memshape = -1;
b->block_gid = -1;
b->field_gid = -1;
b->have_layout = 0;
TRY( b->dcreate_prop = h5priv_create_hdf5_property(f, H5P_DATASET_CREATE) );
return H5_SUCCESS;
}
/*!
\ingroup h5_core_filehandling
Open file with name \c filename. This function is available in the paralell
and serial version. In the serial case \c comm may have any value.
\return File handle.
\return NULL on error.
*/
static h5_err_t
open_file (
h5_file_t* const f,
const char* filename, /*!< The name of the data file to open. */
h5_int32_t flags, /*!< The access mode for the file. */
MPI_Comm comm /*!< MPI communicator */
) {
#if !defined(PARALLEL_IO)
#pragma unused comm
#endif
h5_info (f, "Opening file %s.", filename);
TRY( h5priv_set_hdf5_errorhandler (f, H5E_DEFAULT, h5priv_error_handler, NULL) );
TRY( h5_set_stepname_fmt (f, H5_STEPNAME, H5_STEPWIDTH) );
f->xfer_prop = f->create_prop = f->access_prop = H5P_DEFAULT;
f->comm = 0; /* init values for serial case */
f->nprocs = 1;
f->myproc = 0;
#ifdef PARALLEL_IO
f->comm = comm;
TRY( h5priv_mpi_comm_size (f, comm, &f->nprocs) );
TRY( h5priv_mpi_comm_rank (f, comm, &f->myproc) );
/* xfer_prop: also used for parallel I/O, during actual writes
rather than the access_prop which is for file creation. */
TRY( f->xfer_prop = h5priv_create_hdf5_property(f, H5P_DATASET_XFER) );
TRY( f->access_prop = h5priv_create_hdf5_property(f, H5P_FILE_ACCESS) );
TRY( f->create_prop = h5priv_create_hdf5_property(f, H5P_FILE_CREATE) );
/* select the HDF5 VFD */
if (flags & H5_VFD_MPIPOSIX) {
h5_info(f, "Selecting MPI-POSIX VFD");
hbool_t use_gpfs = 0; // TODO autodetect GPFS?
TRY( h5priv_set_hdf5_fapl_mpiposix_property(f,
f->access_prop, comm, use_gpfs) );
} else {
h5_info(f, "Selecting MPI-IO VFD");
TRY( h5priv_set_hdf5_fapl_mpio_property(f,
f->access_prop, comm, MPI_INFO_NULL) );
if (flags & H5_VFD_INDEPENDENT) {
h5_info(f, "MPI-IO: Using independent mode");
} else {
h5_info(f, "MPI-IO: Using collective mode");
TRY( h5priv_set_hdf5_dxpl_mpio_property(f,
f->xfer_prop, H5FD_MPIO_COLLECTIVE) );
}
}
#endif /* PARALLEL_IO */
#ifdef H5_USE_LUSTRE
TRY( h5_optimize_for_lustre(f, filename) );
#endif
if (flags & H5_O_RDONLY) {
f->file = H5Fopen (filename, H5F_ACC_RDONLY, f->access_prop);
}
else if (flags & H5_O_WRONLY){
f->file = H5Fcreate (filename, H5F_ACC_TRUNC, f->create_prop,
f->access_prop);
f->empty = 1;
}
else if (flags & H5_O_APPEND || flags & H5_O_RDWR) {
int fd = open (filename, O_RDONLY, 0);
if ((fd == -1) && (errno == ENOENT)) {
f->file = H5Fcreate (filename, H5F_ACC_TRUNC,
f->create_prop, f->access_prop);
f->empty = 1;
}
else if (fd != -1) {
close (fd);
f->file = H5Fopen (filename, H5F_ACC_RDWR,
f->access_prop);
}
}
else {
return h5_error (
f,
H5_ERR_INVAL,
"Invalid file access mode \"%d\".", flags);
}
if (f->file < 0)
return h5_error (
f,
H5_ERR_HDF5,
"Cannot open file \"%s\" with mode \"%d\"",
filename, flags);
TRY( f->root_gid = h5priv_open_hdf5_group (f, f->file, "/" ) );
f->mode = flags;
f->step_gid = -1;
f->throttle = 0;
sprintf (
f->step_name,
"%s#%0*lld",
f->prefix_step_name, f->width_step_idx, (long long)f->step_idx);
TRY( h5upriv_open_file (f) );
TRY( h5bpriv_open_file (f) );
#ifndef PARALLEL_IO
TRY( h5tpriv_open_file (f) );
#endif
return H5_SUCCESS;
}
h5_file_t*
h5_open_file (
const char* filename, /*!< The name of the data file to open. */
h5_int32_t flags, /*!< The access mode for the file. */
MPI_Comm comm, /*!< MPI communicator */
const char* funcname /*!< calling function name */
) {
h5_file_t* f = NULL;
f = (h5_file_t*) malloc (sizeof (h5_file_t));
if (f == NULL) {
fprintf(
stderr,
"E: %s: Can't open file %s. Not enough memory!",
funcname,
filename);
return NULL;
}
memset (f, 0, sizeof (h5_file_t));
f->__funcname = funcname;
if (open_file (f, filename, flags, comm) < 0) {
if (f != NULL) {
/* Oops, cannot open file. We release the memory allocated for
f only, there is most likely more allocated memory we do
*not* release.
We don't use the wrapper function because we don't know
wheter it will work or not! */
free (f);
}
return NULL;
}
return f;
}
/*!
\ingroup h5_private
\internal
De-initialize H5Block internal structure. Open HDF5 objects are
closed and allocated memory freed.
\return H5_SUCCESS or error code
*/
static h5_err_t
h5upriv_close_file (
h5_file_t* const f /*!< file handle */
) {
struct h5u_fdata* u = f->u;
h5_debug (f, "%s ()", __func__);
f->__errno = H5_SUCCESS;
TRY( h5priv_close_hdf5_dataspace (f, u->shape) );
TRY( h5priv_close_hdf5_dataspace (f, u->diskshape) );
TRY( h5priv_close_hdf5_dataspace (f, u->memshape) );
TRY( h5priv_close_hdf5_property (f, u->dcreate_prop) );
free (f->u);
f->u = NULL;
return f->__errno;
}
/*!
\ingroup h5block_private
\internal
De-initialize H5Block internal structure. Open HDF5 objects are
closed and allocated memory freed.
\return H5_SUCCESS or error code
*/
static h5_err_t
h5bpriv_close_file (
h5_file_t* const f /*!< IN: file handle */
) {
struct h5b_fdata* b = f->b;
h5_debug (f, "%s ()", __func__);
TRY( h5priv_close_hdf5_group (f, b->block_gid) );
TRY( h5priv_close_hdf5_group (f, b->field_gid) );
TRY( h5priv_close_hdf5_dataspace (f, b->shape) );
TRY( h5priv_close_hdf5_dataspace (f, b->diskshape) );
TRY( h5priv_close_hdf5_dataspace (f, b->memshape) );
TRY( h5priv_close_hdf5_property (f, b->dcreate_prop) );
#if defined(PARALLEL_IO)
TRY( h5priv_mpi_type_free (f, &b->partition_mpi_t) );
#endif
free (f->b);
f->b = NULL;
return H5_SUCCESS;
}
/*!
\ingroup h5_core_filehandling
The h5_close_file() call writes all buffered data to disk, releases
all previously allocated memory and terminates access to the associated
HDF5 file.
\return H5_SUCCESS or error code
*/
h5_err_t
h5_close_file (
h5_file_t* const f /*!< file handle */
) {
h5_debug (f, "%s ()", __func__);
f->__errno = H5_SUCCESS;
CHECK_FILEHANDLE (f);
TRY( h5priv_close_step (f) );
TRY( h5upriv_close_file (f) );
TRY( h5bpriv_close_file (f) );
#ifndef PARALLEL_IO
TRY( h5tpriv_close_file (f) );
#endif
TRY( h5priv_close_hdf5_property (f, f->xfer_prop) );
TRY( h5priv_close_hdf5_property (f, f->access_prop) );
TRY( h5priv_close_hdf5_property (f, f->create_prop) );
TRY( h5priv_close_hdf5_group (f, f->root_gid) );
TRY( h5priv_close_hdf5_file (f, f->file) );
free (f);
h5_debug (f, "%s (): done", __func__);
return H5_SUCCESS;
}
/*!
\ingroup h5_core_filehandling
Define format of the step names.
Example: ==H5FedDefineStepNameFormat( f, "Step", 6 )== defines step names
like ==Step#000042==.
\return \c H5_SUCCESS or error code
*/
h5_err_t
h5_set_stepname_fmt (
h5_file_t* const f,
const char* name,
int width
) {
if (width < 0) width = 0;
else if (width > H5_STEPNAME_LEN - 1) width = H5_STEPNAME_LEN - 1;
strncpy (
f->prefix_step_name,
name,
H5_STEPNAME_LEN - 1);
f->width_step_idx = width;
return H5_SUCCESS;
}
/*!
\ingroup h5_core_filehandling
Get format of the step names.
\return \c H5_SUCCESS or error code
*/
h5_err_t
h5_get_stepname_fmt (
h5_file_t* const f, /*!< Handle to file */
char* name, /*!< OUT: Prefix */
int l_name, /*!< length of buffer name */
int* width /*!< OUT: Width of the number */
) {
#pragma unused f
#pragma unused name
#pragma unused l_name
#pragma unused width
return h5_error_not_implemented (f, __FILE__, __func__, __LINE__);
}
/*!
\ingroup h5_core_filehandling
Get current step number.
\return Current step number or error code
*/
h5_id_t
h5_get_step (
h5_file_t* const f /*!< file handle */
) {
return h5_error_not_implemented (f, __FILE__, __func__, __LINE__);
}
/*!
\ingroup h5_core_filehandling
Get number of processes.
\return Number of processes or error code
*/
int
h5_get_num_procs (
h5_file_t* const f /*!< file handle */
) {
return f->nprocs;
}
/*!
\ingroup h5_core_filehandling
Provides access to the underlying HDF5 file handle.
\return Number of steps or error code
*/
hid_t
h5_get_hdf5_file(
h5_file_t* const f /*!< file handle */
) {
return f->file;
}
/*!
\ingroup h5_core_filehandling
Get number of steps.
\return Number of steps or error code
*/
h5_size_t
h5_get_num_steps(
h5_file_t* const f /*!< file handle */
) {
return h5_get_num_hdf5_groups_matching_prefix (
f,
f->step_gid,
f->prefix_step_name);
}
/*!
\ingroup h5_core_filehandling
Start traversing steps.
\return \c H5_SUCCESS or error code
*/
h5_err_t
h5_start_traverse_steps (
h5_file_t* const f /*!< file handle */
) {
return h5_error_not_implemented (f, __FILE__, __func__, __LINE__);
}
/*!
\ingroup h5_core_filehandling
Go to next step.
\return \c H5_SUCCESS or error code
*/
h5_err_t
h5_traverse_steps (
h5_file_t* const f /*!< file handle */
) {
return h5_error_not_implemented (f, __FILE__, __func__, __LINE__);
}
char *
h5_strdupfor2c (
const char *s,
const ssize_t len
) {
char *dup = (char*)malloc ( len + 1 );
strncpy ( dup, s, len );
char *p = dup + len;
do {
*p-- = '\0';
} while ( *p == ' ' );
return dup;
}
char *
h5_strc2for (
char * const str,
const ssize_t l_str
) {
size_t len = strlen ( str );
memset ( str+len, ' ', l_str-len );
return str;
}