h5_file.c 20.8 KB
Newer Older
1
/*
gsell's avatar
gsell committed
2
  Copyright (c) 2006-2016, The Regents of the University of California,
3 4 5 6 7 8 9 10 11 12
  through Lawrence Berkeley National Laboratory (subject to receipt of any
  required approvals from the U.S. Dept. of Energy) and the Paul Scherrer
  Institut (Switzerland).  All rights reserved.

  License: see file COPYING in top level of source distribution.
*/

#include <unistd.h>
#include <errno.h>
#include <fcntl.h>
gsell's avatar
gsell committed
13
#include <string.h>
14

15
#include "h5core/h5_log.h"
16

17
#include "private/h5_file.h"
gsell's avatar
gsell committed
18
#include "private/h5_hdf5.h"
19

gsell's avatar
gsell committed
20 21 22 23
#include "private/h5_model.h"
#include "private/h5_mpi.h"
#include "private/h5u_io.h"
#include "private/h5b_io.h"
24

25
#include "h5core/h5_err.h"
26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52
#include "h5core/h5_syscall.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 (
	const h5_file_t f_               /*!< filehandle  to check validity of */
	) {
        h5_file_p f = (h5_file_p)f_;
	if (f == NULL || f_ == H5_FAILURE || f->file < 0 || f->u == NULL || f->b == NULL) {
		return h5_error (
			H5_ERR_BADF,
			"Called with bad filehandle.");
	}
	return H5_SUCCESS;
}

gsell's avatar
gsell committed
53 54 55 56 57 58
hid_t
h5_get_hdf5_file(
	const h5_file_t f_		/*!< file handle		*/
	) {
        h5_file_p f = (h5_file_p)f_;
	H5_CORE_API_ENTER (hid_t, "f=%p", f);
gsell's avatar
gsell committed
59
	H5_RETURN (f->file);
gsell's avatar
gsell committed
60 61
}

62
/*!
63
  Initialize H5hut
64 65 66 67
*/
static herr_t
hdf5_error_handler (
	hid_t estack_id,
gsell's avatar
gsell committed
68
	void*  __f
69 70
	) {
	UNUSED_ARGUMENT (__f);
71
	if (h5_get_loglevel() >= 5) {
72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91
		H5Eprint (estack_id, stderr);
	}
	return 0;
}

static inline h5_err_t
mpi_init (
	const h5_file_p f
	) {
	H5_INLINE_FUNC_ENTER (h5_err_t);
#ifdef PARALLEL_IO
	TRY (h5priv_mpi_comm_size (f->props->comm, &f->nprocs));
	TRY (h5priv_mpi_comm_rank (f->props->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->props->xfer_prop = hdf5_create_property(H5P_DATASET_XFER));
	TRY (f->props->access_prop = hdf5_create_property(H5P_FILE_ACCESS));

	/* select the HDF5 VFD */
gsell's avatar
gsell committed
92
#if H5_VERSION_LE(1,8,12)
93
	if ((f->props->flags & H5_VFD_MPIO_POSIX)) {
94 95 96 97 98
		h5_info("Selecting MPI-POSIX VFD");
		hbool_t use_gpfs = 0; // TODO autodetect GPFS?
		TRY (hdf5_set_fapl_mpiposix_property (f->props->access_prop,
                                                     f->props->comm, use_gpfs));

99
        } else if ((f->props->flags & H5_VFD_CORE)) {
100 101 102
		h5_info("Selecting CORE VFD");
                TRY (hdf5_set_fapl_core (f->props->access_prop,
                                         f->props->align, 1));
gsell's avatar
gsell committed
103
        } else if ((f->props->flags & H5_VFD_MPIO_INDEPENDENT)){
104
                h5_info("Selecting MPI-IO VFD, using independent mode");
105 106
		TRY (hdf5_set_fapl_mpio_property (f->props->access_prop,
                                                  f->props->comm, MPI_INFO_NULL));
107 108 109
                TRY (hdf5_set_dxpl_mpio_property (f->props->xfer_prop,
                                                  H5FD_MPIO_INDEPENDENT) );
        } else {
110
                // default is MPI-IO collective mode
111 112 113 114 115
		h5_info("Selecting MPI-IO VFD, using collective mode");
		TRY (hdf5_set_fapl_mpio_property (f->props->access_prop,
                                                  f->props->comm, MPI_INFO_NULL));
                TRY (hdf5_set_dxpl_mpio_property (f->props->xfer_prop,
                                                  H5FD_MPIO_COLLECTIVE) );
116
	}
gsell's avatar
gsell committed
117 118 119 120 121 122 123 124 125 126 127 128 129
#else
	// VFD_MPIO_POSIX has been removed in HDF5 1.8.13
        if ((f->props->flags & H5_VFD_CORE)) {
		h5_info("Selecting CORE VFD");
                TRY (hdf5_set_fapl_core (f->props->access_prop,
                                         f->props->align, 1));
        } else if ((f->props->flags & H5_VFD_MPIO_INDEPENDENT)){
                h5_info("Selecting MPI-IO VFD, using independent mode");
		TRY (hdf5_set_fapl_mpio_property (f->props->access_prop,
                                                  f->props->comm, MPI_INFO_NULL));
                TRY (hdf5_set_dxpl_mpio_property (f->props->xfer_prop,
                                                  H5FD_MPIO_INDEPENDENT) );
        } else {
130
                // default is MPI-IO collective mode
gsell's avatar
gsell committed
131 132 133 134 135 136 137
		h5_info("Selecting MPI-IO VFD, using collective mode");
		TRY (hdf5_set_fapl_mpio_property (f->props->access_prop,
                                                  f->props->comm, MPI_INFO_NULL));
                TRY (hdf5_set_dxpl_mpio_property (f->props->xfer_prop,
                                                  H5FD_MPIO_COLLECTIVE) );
	}
#endif
138 139 140 141 142 143
#ifdef H5_USE_LUSTRE
	if (f->flags & H5_FS_LUSTRE) {
		TRY (h5_optimize_for_lustre(f, filename));
	}
#endif
#endif /* PARALLEL_IO */
gsell's avatar
gsell committed
144
	H5_RETURN (H5_SUCCESS);
145 146 147 148 149 150 151 152
}

static inline h5_err_t
set_alignment (
	const h5_file_p f
	) {
	H5_INLINE_FUNC_ENTER (h5_err_t);
	if ( f->props->align != 0 ) {
gsell's avatar
gsell committed
153 154 155 156
		h5_info (
			"Setting HDF5 alignment to %lld bytes "
			"with threshold at half that many bytes.",
			(long long int)f->props->align);
157 158 159 160
		TRY (hdf5_set_alignment_property (
                             f->props->access_prop,
                             f->props->align / 2,
                             f->props->align));
gsell's avatar
gsell committed
161 162 163
		h5_info (
			"Setting HDF5 meta block to %lld bytes",
			(long long int)f->props->align);
164 165
		TRY (H5Pset_meta_block_size (f->props->access_prop, f->props->align));
	}
gsell's avatar
gsell committed
166
	H5_RETURN (H5_SUCCESS);
167 168 169 170
}

static inline h5_err_t
set_default_file_props (
gsell's avatar
gsell committed
171
        h5_prop_file_t* const _props
172 173
        ) {
        H5_INLINE_FUNC_ENTER (h5_err_t);
gsell's avatar
gsell committed
174
        h5_prop_file_t* props = (h5_prop_file_t*)_props;
gsell's avatar
gsell committed
175
        bzero (props, sizeof (*props));
176 177
        props->class = H5_PROP_FILE;
        TRY (props->prefix_step_name = h5_calloc (1, H5_STEPNAME_LEN));
178
        strncpy (
179
                props->prefix_step_name,
180 181
                H5_STEPNAME,
                H5_STEPNAME_LEN - 1);
182 183
        props->width_step_idx = H5_STEPWIDTH;
        props->comm = MPI_COMM_WORLD;
gsell's avatar
gsell committed
184
        H5_RETURN (H5_SUCCESS);
185 186 187
}

h5_err_t
188 189
h5_set_prop_file_mpio_collective (
        h5_prop_t _props,
190 191
        MPI_Comm* comm
        ) {
gsell's avatar
gsell committed
192
        h5_prop_file_t* props = (h5_prop_file_t*)_props;
193
        H5_CORE_API_ENTER (h5_err_t, "props=%p, comm=%p", props, comm);
194
        
195
        if (props->class != H5_PROP_FILE) {
gsell's avatar
gsell committed
196
                H5_LEAVE (
197 198
                        h5_error (
                                H5_ERR_INVAL,
gsell's avatar
gsell committed
199
                                "Invalid property class: %lld",
200 201 202 203 204
				(long long int)props->class));
        }
        props->flags &= ~(H5_VFD_MPIO_POSIX | H5_VFD_MPIO_INDEPENDENT | H5_VFD_CORE);
        props->flags |= H5_VFD_MPIO_COLLECTIVE;
        props->comm = *comm;
205 206 207 208 209
	if (props->throttle > 0) {
		h5_warn ("Throttling is not permitted with collective VFD. Reset throttling.");
		props->throttle = 0;
	}

gsell's avatar
gsell committed
210
        H5_RETURN (H5_SUCCESS);
211 212 213 214 215 216 217
}

h5_err_t
h5_set_prop_file_mpio_independent (
        h5_prop_t _props,
        MPI_Comm* comm
        ) {
gsell's avatar
gsell committed
218
        h5_prop_file_t* props = (h5_prop_file_t*)_props;
219 220 221
        H5_CORE_API_ENTER (h5_err_t, "props=%p, comm=%p", props, comm);
        
        if (props->class != H5_PROP_FILE) {
gsell's avatar
gsell committed
222
                H5_LEAVE (
223 224 225 226 227 228 229 230
                        h5_error (
                                H5_ERR_INVAL,
                                "Invalid property class: %lld",
				(long long int)props->class));
        }
        props->flags &= ~(H5_VFD_MPIO_COLLECTIVE | H5_VFD_MPIO_POSIX | H5_VFD_CORE);
        props->flags |= H5_VFD_MPIO_INDEPENDENT;
        props->comm = *comm;
gsell's avatar
gsell committed
231
        H5_RETURN (H5_SUCCESS);
232 233
}

234
#if H5_VERSION_LE(1,8,12)
235 236 237 238 239
h5_err_t
h5_set_prop_file_mpio_posix (
        h5_prop_t _props,
        MPI_Comm* comm
        ) {
gsell's avatar
gsell committed
240
        h5_prop_file_t* props = (h5_prop_file_t*)_props;
241 242 243
        H5_CORE_API_ENTER (h5_err_t, "props=%p, comm=%p", props, comm);
        
        if (props->class != H5_PROP_FILE) {
gsell's avatar
gsell committed
244
                H5_LEAVE (
245 246 247 248 249 250 251 252
                        h5_error (
                                H5_ERR_INVAL,
                                "Invalid property class: %lld",
				(long long int)props->class));
        }
        props->flags &= ~(H5_VFD_MPIO_COLLECTIVE | H5_VFD_MPIO_POSIX | H5_VFD_CORE);
        props->flags |= H5_VFD_MPIO_INDEPENDENT;
        props->comm = *comm;
gsell's avatar
gsell committed
253
        H5_RETURN (H5_SUCCESS);
254
}
255
#endif
256 257 258

h5_err_t
h5_set_prop_file_core_vfd (
259
        h5_prop_t _props,
gsell's avatar
gsell committed
260
	const h5_int64_t increment
261
        ) {
gsell's avatar
gsell committed
262
        h5_prop_file_t* props = (h5_prop_file_t*)_props;
263
        H5_CORE_API_ENTER (h5_err_t, "props=%p, increment=%lld", props, (long long int)increment);
264 265
        
        if (props->class != H5_PROP_FILE) {
gsell's avatar
gsell committed
266
                H5_LEAVE (
267 268 269 270
                        h5_error (
                                H5_ERR_INVAL,
                                "Invalid property class: %lld",
				(long long int)props->class));
271
        }
272 273 274
        props->flags &= ~(H5_VFD_MPIO_COLLECTIVE | H5_VFD_MPIO_INDEPENDENT | H5_VFD_MPIO_POSIX);
        props->flags |= H5_VFD_MPIO_INDEPENDENT;
        props->comm = MPI_COMM_SELF;
275
	props->increment = increment;
276
	if (props->throttle > 0) {
gsell's avatar
gsell committed
277
		h5_warn ("Throttling is not permitted with core VFD. Reset throttling.");
278 279
		props->throttle = 0;
	}
gsell's avatar
gsell committed
280
        H5_RETURN (H5_SUCCESS);
281 282
}

283

284 285
h5_err_t
h5_set_prop_file_align (
286
        h5_prop_t _props,
gsell's avatar
gsell committed
287
        const h5_int64_t align
288
        ) {
gsell's avatar
gsell committed
289
        h5_prop_file_t* props = (h5_prop_file_t*)_props;
gsell's avatar
gsell committed
290 291
        H5_CORE_API_ENTER (
		h5_err_t,
292 293 294
		"props=%p, align=%lld",
		props, (long long int)align);
        if (props->class != H5_PROP_FILE) {
gsell's avatar
gsell committed
295
                H5_LEAVE (
296 297
                        h5_error (
                                H5_ERR_INVAL,
gsell's avatar
gsell committed
298
                                "Invalid property class: %lld",
299
				(long long int)props->class));
300
        }
301
        props->align = align;
gsell's avatar
gsell committed
302
        H5_RETURN (H5_SUCCESS);
303 304 305 306
}

h5_err_t
h5_set_prop_file_throttle (
307
        h5_prop_t _props,
gsell's avatar
gsell committed
308
        const h5_int64_t throttle
309
        ) {
gsell's avatar
gsell committed
310
        h5_prop_file_t* props = (h5_prop_file_t*)_props;
gsell's avatar
gsell committed
311 312
        H5_CORE_API_ENTER (
		h5_err_t,
313 314 315
		"props=%p, throttle=%lld",
		props, (long long int)throttle);
        if (props->class != H5_PROP_FILE) {
gsell's avatar
gsell committed
316
                H5_LEAVE (
317 318
                        h5_error (
                                H5_ERR_INVAL,
gsell's avatar
gsell committed
319
                                "Invalid property class: %lld",
320
				(long long int)props->class));
321
        }
322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339
	// throttle only if VFD is MPIO independent od POSIX
	h5_int64_t mask = H5_VFD_MPIO_INDEPENDENT;
#if H5_VERSION_LE(1,8,12)
	mask |= H5_VFD_MPIO_POSIX;
#endif
	if (! (props->flags & mask)) {
#if H5_VERSION_LE(1,8,12)
		h5_warn (
			"Throttling is only permitted with the MPI-POSIX "
			"or MPI-IO Independent VFD. Property ignored." );
#else
		h5_warn (
			"Throttling is only permitted with "
			"the MPI-IO Independent VFD. Property ignored.");
#endif
		props->throttle = 0;
	}

340
        props->throttle = throttle;
gsell's avatar
gsell committed
341
        H5_RETURN (H5_SUCCESS);
342 343 344 345 346
}


h5_prop_t
h5_create_prop (
gsell's avatar
gsell committed
347
        const h5_int64_t class
348
        ) {
gsell's avatar
gsell committed
349 350 351 352
        H5_CORE_API_ENTER (
		h5_prop_t,
		"class=%lld",
		(long long int)class);
353 354 355 356 357 358 359
        h5_prop_t* prop;
        switch (class) {
        case H5_PROP_FILE:
                TRY (prop = h5_calloc (1, sizeof (h5_prop_file_t)));
                set_default_file_props ((h5_prop_file_t*)prop);
                break;
        default:
gsell's avatar
gsell committed
360
                H5_LEAVE (
361 362
                        h5_error (
                                H5_ERR_INVAL,
gsell's avatar
gsell committed
363 364
                                "Invalid property class: %lld",
				(long long int)class));
365
        }
gsell's avatar
gsell committed
366
        H5_RETURN ((h5_prop_t)prop);
367 368 369 370 371 372 373 374 375 376 377 378 379 380 381
}

h5_err_t
h5_close_prop (
        h5_prop_t _prop
        ) {
        h5_prop_p prop = (h5_prop_p)_prop;
        H5_CORE_API_ENTER (h5_err_t, "prop=%p", prop);
        switch (prop->class) {
        case H5_PROP_FILE: {
                h5_prop_file_t* file_prop = (h5_prop_file_t*)prop;
                TRY (h5_free (file_prop->prefix_step_name));
                break;
        }
        default:
gsell's avatar
gsell committed
382
                H5_LEAVE (
383 384
                        h5_error (
                                H5_ERR_INVAL,
gsell's avatar
gsell committed
385 386
                                "Invalid property class: %lld",
				(long long int)prop->class));
387
        }
gsell's avatar
gsell committed
388
        H5_RETURN (h5_free (prop));
389 390 391 392 393 394
}

static inline h5_err_t
open_file (
	const h5_file_p f,
	const char* const filename,
gsell's avatar
gsell committed
395
	const h5_int32_t mode
396 397 398 399
	) {
	H5_INLINE_FUNC_ENTER (h5_err_t);
        h5_info ("Opening file %s.", filename);

400
        f->props->flags |= mode;
401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419

        f->nprocs = 1; // queried later
        f->myproc = 0; // queried later
        f->step_gid = -1;

        TRY (f->step_name = h5_calloc (2, H5_STEPNAME_LEN));
        sprintf (
                f->step_name,
                "%s#%0*lld",
                f->props->prefix_step_name,
                f->props->width_step_idx, (long long)f->step_idx);

        TRY (hdf5_set_errorhandler (H5E_DEFAULT, hdf5_error_handler, NULL));
        
        f->props->xfer_prop = f->props->access_prop = H5P_DEFAULT;
        TRY (f->props->create_prop = hdf5_create_property (H5P_FILE_CREATE));
	TRY (mpi_init (f));              // noop if serial
	TRY (set_alignment (f));

420
	if (f->props->flags & H5_O_RDONLY) {
421 422
		f->file = H5Fopen (filename, H5F_ACC_RDONLY, f->props->access_prop);
	}
423 424 425 426
	else if (f->props->flags & H5_O_WRONLY){
		f->file = H5Fcreate (
                        filename, H5F_ACC_TRUNC, f->props->create_prop,
                        f->props->access_prop);
427 428
		f->empty = 1;
	}
429
	else if (f->props->flags & H5_O_APPENDONLY || f->props->flags & H5_O_RDWR) {
430 431
		int fd = open (filename, O_RDONLY, 0);
		if ((fd == -1) && (errno == ENOENT)) {
432 433 434
			f->file = H5Fcreate (
                                filename, H5F_ACC_TRUNC,
                                f->props->create_prop, f->props->access_prop);
435 436 437 438 439 440 441 442 443
			f->empty = 1;
		}
		else if (fd != -1) {
			close (fd);
			f->file = H5Fopen (filename, H5F_ACC_RDWR,
					   f->props->access_prop);
		}
	}
	else {
gsell's avatar
gsell committed
444
		H5_LEAVE (
445 446
			h5_error (
				H5_ERR_INVAL,
gsell's avatar
gsell committed
447
				"Invalid file access mode '%lld'.",
448
				(long long int)f->props->flags & 0xff));
449 450 451
	}
	
	if (f->file < 0)
gsell's avatar
gsell committed
452
		H5_LEAVE (
453 454
			h5_error (
				H5_ERR_HDF5,
455 456
				"Cannot open file '%s' with mode '%s'",
				filename, H5_O_MODES[f->props->flags & 0xff]));
457 458 459 460 461
	TRY (f->root_gid = hdf5_open_group (f->file, "/" ));

	TRY (h5upriv_open_file (f));
	TRY (h5bpriv_open_file (f));

gsell's avatar
gsell committed
462
	H5_RETURN (H5_SUCCESS);
463 464 465 466
}

h5_file_t
h5_open_file2 (
gsell's avatar
gsell committed
467 468 469
	const char* const filename,
	const h5_int32_t mode,
        const h5_prop_t props_
470
	) {
gsell's avatar
gsell committed
471
        h5_prop_file_t* const props = (h5_prop_file_t*)props_;
472 473 474 475 476 477 478 479 480 481 482 483 484
	H5_CORE_API_ENTER (h5_file_t,
			   "filename='%s', mode=%d, props=%p",
			   filename, mode, props);
                
	h5_file_p f = NULL;
	TRY (f = h5_calloc (1, sizeof (*f)));
	
        TRY (f->props = (h5_prop_file_t*)h5_create_prop (H5_PROP_FILE));
        TRY (set_default_file_props (f->props));
        TRY (h5_set_stepname_fmt ((uintptr_t)f, H5_STEPNAME, H5_STEPWIDTH));
                
        if (props != H5_PROP_DEFAULT) {
                if (props->class != H5_PROP_FILE) {
gsell's avatar
gsell committed
485
                        H5_LEAVE (
486 487 488
                                h5_error (
                                        H5_ERR_INVAL,
                                        "Invalid property class: %lld.",
gsell's avatar
gsell committed
489
                                        (long long int)props->class));
490 491
                }
                f->props->comm = props->comm;
492
                f->props->flags = props->flags;
493 494 495 496 497 498 499 500 501 502 503 504
                f->props->throttle = props->throttle;
                f->props->align = props->align;

                strncpy (
                        f->props->prefix_step_name,
                        props->prefix_step_name,
                        H5_STEPNAME_LEN - 1);
                f->props->width_step_idx = props->width_step_idx;
        }

	TRY (open_file (f, filename, mode));

gsell's avatar
gsell committed
505
	H5_RETURN ((h5_file_t)f);
506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523
}

/*!
  \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.

  \param[in]	filename	The name of the data file to open.
  \param[in]	flags		The access mode for the file.
  \param[in]	comm		MPI communicator
  \param[in]	align		Number of bytes for setting alignment,
				metadata block size, etc. Set to 0 to disable.

  \return File handle.
  \return H5_ERR  on error.
*/

gsell's avatar
gsell committed
524
h5_file_p
525
h5_open_file1 (
526 527 528
	const char* filename,
	h5_int32_t mode,
	MPI_Comm comm,
gsell's avatar
gsell committed
529
	const h5_size_t align
530
	) {
gsell's avatar
gsell committed
531
	H5_CORE_API_ENTER (
gsell's avatar
gsell committed
532
		h5_file_p,
gsell's avatar
gsell committed
533 534
		"filename='%s', mode=%d, comm=?, align=%llu",
		filename, mode, (long long int)align);
535 536 537
        h5_prop_file_t* props;
        h5_file_t f;
        TRY (props = (h5_prop_file_t*)h5_create_prop (H5_PROP_FILE));
538
        TRY (h5_set_prop_file_mpio_collective ((h5_prop_t)props, &comm));
539 540 541
        TRY (h5_set_prop_file_align ((h5_prop_t)props, align));
        TRY (f = h5_open_file2 (filename, mode, (h5_prop_t)props));
        TRY (h5_close_prop ((h5_prop_t)props));
gsell's avatar
gsell committed
542
	h5_file_p _f = (h5_file_p)f;
gsell's avatar
gsell committed
543
        H5_RETURN (_f);
544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577

}

/*!
  \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 (
	const h5_file_t f_              /*!< file handle */
	) {
        h5_file_p f = (h5_file_p)f_;
	H5_CORE_API_ENTER (h5_err_t, "f=%p", f);
	h5_errno = H5_SUCCESS;

	CHECK_FILEHANDLE (f);

	TRY (h5priv_close_step (f));
	TRY (h5upriv_close_file (f));
	TRY (h5bpriv_close_file (f));
	TRY (hdf5_close_property (f->props->xfer_prop));
	TRY (hdf5_close_property (f->props->access_prop));
	TRY (hdf5_close_property (f->props->create_prop));
	TRY (hdf5_close_group (f->root_gid));
        TRY (hdf5_flush (f->file, H5F_SCOPE_GLOBAL));
        TRY (h5_close_prop ((h5_prop_t)f->props));
	TRY (hdf5_close_file (f->file));
        TRY (h5_free (f->step_name));
 	TRY (h5_free (f));
gsell's avatar
gsell committed
578
	H5_RETURN (H5_SUCCESS);
579 580 581 582 583 584 585
}

h5_err_t
h5_close_hdf5 (
        void
        ) {
	H5_CORE_API_ENTER (h5_err_t, "%s", "");
586
	TRY (ret_value = hdf5_close ());
gsell's avatar
gsell committed
587
	H5_RETURN (ret_value);
588 589 590 591 592 593 594 595
}

h5_err_t
h5_flush_step (
	const h5_file_t f_
	) {
        h5_file_p f = (h5_file_p)f_;
	H5_CORE_API_ENTER (h5_err_t, "f=%p", f);
596
	TRY (ret_value = hdf5_flush (f->step_gid, H5F_SCOPE_LOCAL));
gsell's avatar
gsell committed
597
	H5_RETURN (ret_value);
598 599 600 601 602 603 604 605
}

h5_err_t
h5_flush_file (
	const h5_file_t f_
	) {
        h5_file_p f = (h5_file_p)f_;
	H5_CORE_API_ENTER (h5_err_t, "f=%p", f);
606
	TRY (ret_value = hdf5_flush (f->file, H5F_SCOPE_GLOBAL));
gsell's avatar
gsell committed
607
	H5_RETURN (ret_value);
608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638
}


/*!
  \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 (
	const h5_file_t f_,
	const char* name,
	int width
	) {
        h5_file_p f = (h5_file_p)f_;
	H5_CORE_API_ENTER (h5_err_t,
                           "f=%p, name='%s', width=%d",
                           f, name, width);
	if (width < 0) width = 0;
	else if (width > H5_STEPNAME_LEN - 1) width = H5_STEPNAME_LEN - 1;
	strncpy (
		f->props->prefix_step_name,
		name,
		H5_STEPNAME_LEN - 1);
	f->props->width_step_idx = width;

gsell's avatar
gsell committed
639
	H5_RETURN (H5_SUCCESS);
640 641 642 643 644 645 646 647 648 649 650 651
}

/*!
  \ingroup h5_core_filehandling

  Get format of the step names.

  \return \c H5_SUCCESS or error code
*/
h5_err_t
h5_get_stepname_fmt (
	const h5_file_t f_,		/*!< Handle to file		*/
gsell's avatar
gsell committed
652 653 654
	char* const name,			/*!< OUT: Prefix		*/
	const int l_name,			/*!< length of buffer name	*/
	int* const width			/*!< OUT: Width of the number	*/
655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676
	) {
        h5_file_p f = (h5_file_p)f_;
	UNUSED_ARGUMENT (f);
	UNUSED_ARGUMENT (name);
	UNUSED_ARGUMENT (l_name);
	UNUSED_ARGUMENT (width);
	return h5_error_not_implemented ();
}

/*!
  \ingroup h5_core_filehandling

  Get current step number.

  \return Current step number or error code
*/
h5_id_t
h5_get_step (
	const h5_file_t f_		/*!< file handle		*/
	) {
        h5_file_p f = (h5_file_p)f_;
	H5_CORE_API_ENTER (h5_id_t, "f=%p", f);
gsell's avatar
gsell committed
677
	H5_RETURN (f->step_idx);
678 679 680 681 682 683 684 685 686 687 688 689 690 691 692
}

/*!
  \ingroup h5_core_filehandling

  Get number of processes.

  \return Number of processes or error code
*/
int
h5_get_num_procs (
	const h5_file_t f_		/*!< file handle		*/
	) {
        h5_file_p f = (h5_file_p)f_;
	H5_CORE_API_ENTER (int, "f=%p", f);
gsell's avatar
gsell committed
693
	H5_RETURN (f->nprocs);
694 695 696 697 698 699 700 701 702 703 704 705 706 707 708
}

/*!
  \ingroup h5_core_filehandling

  Get number of steps.

  \return Number of steps or error code
*/
h5_ssize_t
h5_get_num_steps(
	const h5_file_t f_		/*!< file handle		*/
	) {
        h5_file_p f = (h5_file_p)f_;
	H5_CORE_API_ENTER (int, "f=%p", f);
709 710 711
	TRY (ret_value = hdf5_get_num_groups_matching_prefix (
		     f->root_gid,
		     f->props->prefix_step_name));
gsell's avatar
gsell committed
712
	H5_RETURN (ret_value);
713 714 715 716 717
}

/*!
  \ingroup h5_core_filehandling

718
  Start traversing steps. 
719 720 721 722 723 724 725 726

  \return \c H5_SUCCESS or error code 
*/
h5_err_t
h5_start_traverse_steps (
	const h5_file_t f_		/*!< file handle		*/
	) {
        h5_file_p f = (h5_file_p)f_;
727 728 729 730 731 732 733 734
	H5_CORE_API_ENTER (int, "f=%p", f);

	/*
	  fast test: Does Step#0 or Step#1 exist?
	  otherwise
	  loop over all steps and get smallest step number
	 */
	
gsell's avatar
gsell committed
735
	H5_RETURN (h5_error_not_implemented ());
736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752
}

/*!
  \ingroup h5_core_filehandling

  Go to next step.

  \return \c H5_SUCCESS or error code 
*/
h5_err_t
h5_traverse_steps (
	const h5_file_t f_		/*!< file handle		*/
	) {
        h5_file_p f = (h5_file_p)f_;
	UNUSED_ARGUMENT (f);
	return h5_error_not_implemented ();
}