IOR
aiori-HDF5.c
Go to the documentation of this file.
1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2  * vim:expandtab:shiftwidth=8:tabstop=8:
3  */
4 /******************************************************************************\
5 * *
6 * Copyright (c) 2003, The Regents of the University of California *
7 * See the file COPYRIGHT for a complete copyright notice and license. *
8 * *
9 ********************************************************************************
10 *
11 * Implement abstract I/O interface for HDF5.
12 *
13 \******************************************************************************/
14 
15 #ifdef HAVE_CONFIG_H
16 #include "config.h"
17 #endif
18 
19 #include <stdio.h> /* only for fprintf() */
20 #include <stdlib.h>
21 #include <sys/stat.h>
22 /* HDF5 routines here still use the old 1.6 style. Nothing wrong with that but
23  * save users the trouble of passing this flag through configure */
24 #define H5_USE_16_API
25 #include <hdf5.h>
26 #include <mpi.h>
27 
28 #include "aiori.h" /* abstract IOR interface */
29 #include "utilities.h"
30 #include "iordef.h"
31 
32 #define NUM_DIMS 1 /* number of dimensions to data set */
33 
34 /******************************************************************************/
35 /*
36  * HDF5_CHECK will display a custom error message and then exit the program
37  */
38 
39 /*
40  * should use MPI_Abort(), not exit(), in this macro; some versions of
41  * MPI, however, hang with HDF5 property lists et al. left unclosed
42  */
43 
44 /*
45  * for versions later than hdf5-1.6, the H5Eget_[major|minor]() functions
46  * have been deprecated and replaced with H5Eget_msg()
47  */
48 #if H5_VERS_MAJOR > 1 && H5_VERS_MINOR > 6
49 #define HDF5_CHECK(HDF5_RETURN, MSG) do { \
50  char resultString[1024]; \
51  herr_t _HDF5_RETURN = (HDF5_RETURN); \
52  \
53  if (_HDF5_RETURN < 0) { \
54  fprintf(stdout, "** error **\n"); \
55  fprintf(stdout, "ERROR in %s (line %d): %s.\n", \
56  __FILE__, __LINE__, MSG); \
57  strcpy(resultString, H5Eget_major((H5E_major_t)_HDF5_RETURN)); \
58  if (strcmp(resultString, "Invalid major error number") != 0) \
59  fprintf(stdout, "HDF5 %s\n", resultString); \
60  strcpy(resultString, H5Eget_minor((H5E_minor_t)_HDF5_RETURN)); \
61  if (strcmp(resultString, "Invalid minor error number") != 0) \
62  fprintf(stdout, "%s\n", resultString); \
63  fprintf(stdout, "** exiting **\n"); \
64  exit(EXIT_FAILURE); \
65  } \
66 } while(0)
67 #else /* ! (H5_VERS_MAJOR > 1 && H5_VERS_MINOR > 6) */
68 #define HDF5_CHECK(HDF5_RETURN, MSG) do { \
69  \
70  if (HDF5_RETURN < 0) { \
71  fprintf(stdout, "** error **\n"); \
72  fprintf(stdout, "ERROR in %s (line %d): %s.\n", \
73  __FILE__, __LINE__, MSG); \
74  /* \
75  * H5Eget_msg(hid_t mesg_id, H5E_type_t* mesg_type, \
76  * char* mesg, size_t size) \
77  */ \
78  fprintf(stdout, "** exiting **\n"); \
79  exit(EXIT_FAILURE); \
80  } \
81 } while(0)
82 #endif /* H5_VERS_MAJOR > 1 && H5_VERS_MINOR > 6 */
83 
84 /**************************** P R O T O T Y P E S *****************************/
85 
87 static aiori_fd_t *HDF5_Create(char *, int flags, aiori_mod_opt_t *);
88 static aiori_fd_t *HDF5_Open(char *, int flags, aiori_mod_opt_t *);
91 static void HDF5_Close(aiori_fd_t *, aiori_mod_opt_t *);
92 static void HDF5_Delete(char *, aiori_mod_opt_t *);
93 static char* HDF5_GetVersion();
94 static void HDF5_Fsync(aiori_fd_t *, aiori_mod_opt_t *);
96 static int HDF5_StatFS(const char *, ior_aiori_statfs_t *, aiori_mod_opt_t *);
97 static int HDF5_MkDir(const char *, mode_t, aiori_mod_opt_t *);
98 static int HDF5_RmDir(const char *, aiori_mod_opt_t *);
99 static int HDF5_Access(const char *, int, aiori_mod_opt_t *);
100 static int HDF5_Stat(const char *, struct stat *, aiori_mod_opt_t *);
101 static void HDF5_Finalize(aiori_mod_opt_t *);
102 static void HDF5_init_xfer_options(aiori_xfer_hint_t * params);
104 
105 /************************** O P T I O N S *****************************/
106 typedef struct{
108 
110  int individualDataSets; /* datasets not shared by all procs */
111  int noFill; /* no fill in file creation */
112  IOR_offset_t setAlignment; /* alignment in bytes */
115 /***************************** F U N C T I O N S ******************************/
116 
117 static option_help * HDF5_options(aiori_mod_opt_t ** init_backend_options, aiori_mod_opt_t * init_values){
118  HDF5_options_t * o = malloc(sizeof(HDF5_options_t));
119 
120  if (init_values != NULL){
121  memcpy(o, init_values, sizeof(HDF5_options_t));
122  }else{
123  memset(o, 0, sizeof(HDF5_options_t));
124  /* initialize the options properly */
125  o->collective_md = 0;
126  o->setAlignment = 1;
127  o->chunk_size = 0;
128  o->mpio.hintsFileName = NULL;
129  }
130 
131  *init_backend_options = (aiori_mod_opt_t*) o;
132 
133  option_help h [] = {
134  /* options imported from MPIIO */
135  {0, "hdf5.hintsFileName","Full name for hints file", OPTION_OPTIONAL_ARGUMENT, 's', & o->mpio.hintsFileName},
136  {0, "hdf5.showHints", "Show MPI hints", OPTION_FLAG, 'd', & o->mpio.showHints},
137  /* generic options */
138  {0, "hdf5.collectiveMetadata", "Use collectiveMetadata (available since HDF5-1.10.0)", OPTION_FLAG, 'd', & o->collective_md},
139  {0, "hdf5.individualDataSets", "Datasets not shared by all procs [not working]", OPTION_FLAG, 'd', & o->individualDataSets},
140  {0, "hdf5.setAlignment", "HDF5 alignment in bytes (e.g.: 8, 4k, 2m, 1g)", OPTION_OPTIONAL_ARGUMENT, 'd', & o->setAlignment},
141  {0, "hdf5.noFill", "No fill in HDF5 file creation", OPTION_FLAG, 'd', & o->noFill},
142  {0, "hdf5.chunkSize", "Chunk size (in terms of dataset elements) to use for I/O", OPTION_FLAG, 'd', & o->chunk_size},
144  };
145  option_help * help = malloc(sizeof(h));
146  memcpy(help, h, sizeof(h));
147  return help;
148 }
149 
150 
151 /************************** D E C L A R A T I O N S ***************************/
152 
154  .name = "HDF5",
155  .name_legacy = NULL,
156  .create = HDF5_Create,
157  .open = HDF5_Open,
158  .xfer = HDF5_Xfer,
159  .close = HDF5_Close,
160  .delete = HDF5_Delete,
161  .get_version = HDF5_GetVersion,
162  .xfer_hints = HDF5_init_xfer_options,
163  .fsync = HDF5_Fsync,
164  .get_file_size = HDF5_GetFileSize,
165  .statfs = HDF5_StatFS,
166  .mkdir = HDF5_MkDir,
167  .rmdir = HDF5_RmDir,
168  .access = HDF5_Access,
169  .stat = HDF5_Stat,
170  .finalize = HDF5_Finalize,
171  .get_options = HDF5_options,
172  .check_params = HDF5_check_params
173 };
174 
175 typedef struct{
176  hid_t fd;
177  hid_t xferPropList; /* xfer property list */
178  hid_t dataSet; /* data set id */
179  hid_t dataSpace; /* data space id */
180  hid_t fileDataSpace; /* file data space id */
181  hid_t memDataSpace; /* memory data space id */
182  int newlyOpenedFile; /* newly opened file */
185 } aiori_h5fd_t;
186 
187 static void SetupDataSet(aiori_h5fd_t *, int flags, aiori_mod_opt_t *);
188 
189 /***************************** F U N C T I O N S ******************************/
191 
193  hints = params;
195  MPIIO_xfer_hints(params);
196 }
197 
199  HDF5_options_t *o = (HDF5_options_t*) options;
200  if (o->setAlignment < 0)
201  ERR("alignment must be non-negative integer");
202  if (o->individualDataSets)
203  ERR("individual data sets not implemented");
204  return 0;
205 }
206 
207 /*
208  * Create and open a file through the HDF5 interface.
209  */
210 static aiori_fd_t *HDF5_Create(char *testFileName, int flags, aiori_mod_opt_t * param)
211 {
212  return HDF5_Open(testFileName, flags, param);
213 }
214 
215 /*
216  * Open a file through the HDF5 interface.
217  */
218 static aiori_fd_t *HDF5_Open(char *testFileName, int flags, aiori_mod_opt_t * param)
219 {
220  HDF5_options_t *o = (HDF5_options_t*) param;
221  hid_t accessPropList, createPropList;
222  hsize_t memStart[NUM_DIMS],
223  dataSetDims[NUM_DIMS],
224  memStride[NUM_DIMS],
225  memCount[NUM_DIMS], memBlock[NUM_DIMS], memDataSpaceDims[NUM_DIMS];
226  int tasksPerDataSet;
227  unsigned fd_mode = (unsigned)0;
228  aiori_h5fd_t * fd = safeMalloc(sizeof(aiori_h5fd_t));
229  MPI_Comm comm;
230  MPI_Info mpiHints = MPI_INFO_NULL;
231 
232  /*
233  * HDF5 uses different flags than those for POSIX/MPIIO
234  */
235  /* set IOR file flags to HDF5 flags */
236  /* -- file open flags -- */
237  if (flags & IOR_RDONLY) {
238  fd_mode |= H5F_ACC_RDONLY;
239  }
240  if (flags & IOR_WRONLY || flags & IOR_RDWR) {
241  fd_mode |= H5F_ACC_RDWR;
242  }
243  if (flags & IOR_APPEND) {
244  fprintf(stdout, "File append not implemented in HDF5\n");
245  }
246  if (flags & IOR_CREAT) {
247  fd_mode |= H5F_ACC_CREAT;
248  }
249  if (flags & IOR_EXCL) {
250  fd_mode |= H5F_ACC_EXCL;
251  }
252  if (flags & IOR_TRUNC) {
253  fd_mode |= H5F_ACC_TRUNC;
254  }
255  if (flags & IOR_DIRECT) {
256  fprintf(stdout, "O_DIRECT not implemented in HDF5\n");
257  }
258 
259  /* set up file creation property list */
260  createPropList = H5Pcreate(H5P_FILE_CREATE);
261  HDF5_CHECK(createPropList, "cannot create file creation property list");
262  /* set size of offset and length used to address HDF5 objects */
263  HDF5_CHECK(H5Pset_sizes
264  (createPropList, sizeof(hsize_t), sizeof(hsize_t)),
265  "cannot set property list properly");
266 
267  /* set up file access property list */
268  accessPropList = H5Pcreate(H5P_FILE_ACCESS);
269  HDF5_CHECK(accessPropList, "cannot create file access property list");
270 
271  /*
272  * someday HDF5 implementation will allow subsets of MPI_COMM_WORLD
273  */
274  /* store MPI communicator info for the file access property list */
275  if (hints->filePerProc) {
276  comm = MPI_COMM_SELF;
277  } else {
278  comm = testComm;
279  }
280 
281  /*
282  * note that with MP_HINTS_FILTERED=no, all key/value pairs will
283  * be in the info object. The info object that is attached to
284  * the file during MPI_File_open() will only contain those pairs
285  * deemed valid by the implementation.
286  */
287  /* show hints passed to file */
288  SetHints(&mpiHints, o->mpio.hintsFileName);
289  if (rank == 0 && o->mpio.showHints) {
290  fprintf(stdout, "\nhints passed to access property list {\n");
291  ShowHints(&mpiHints);
292  fprintf(stdout, "}\n");
293  }
294 
295  HDF5_CHECK(H5Pset_fapl_mpio(accessPropList, comm, mpiHints),
296  "cannot set file access property list");
297 
298  /* set alignment */
299  HDF5_CHECK(H5Pset_alignment(accessPropList, o->setAlignment, o->setAlignment),
300  "cannot set alignment");
301 
302 #ifdef HAVE_H5PSET_ALL_COLL_METADATA_OPS
303  if (o->collective_md) {
304  /* more scalable metadata */
305 
306  HDF5_CHECK(H5Pset_all_coll_metadata_ops(accessPropList, 1),
307  "cannot set collective md read");
308  HDF5_CHECK(H5Pset_coll_metadata_write(accessPropList, 1),
309  "cannot set collective md write");
310  }
311 #endif
312 
313  /* open file */
314  if(! hints->dryRun){
315  if (flags & IOR_CREAT) { /* WRITE */
316  fd->fd = H5Fcreate(testFileName, H5F_ACC_TRUNC, createPropList, accessPropList);
317  HDF5_CHECK(fd->fd, "cannot create file");
318  } else { /* READ or CHECK */
319  fd->fd = H5Fopen(testFileName, fd_mode, accessPropList);
320  HDF5_CHECK(fd->fd, "cannot open file");
321  }
322  }
323 
324  /* show hints actually attached to file handle */
325  if (o->mpio.showHints) {
326  MPI_File *fd_mpiio;
327  HDF5_CHECK(H5Fget_vfd_handle(fd->fd, accessPropList, (void **) &fd_mpiio), "cannot get file handle");
328  MPI_Info info_used;
329  MPI_CHECK(MPI_File_get_info(*fd_mpiio, &info_used), "cannot get file info");
330  if (rank == 0) {
331  /* print the MPI file hints currently used */
332  fprintf(stdout, "\nhints returned from opened file {\n");
333  ShowHints(&info_used);
334  fprintf(stdout, "}\n");
335  }
336  MPI_CHECK(MPI_Info_free(&info_used), "cannot free file info");
337  }
338 
339  /* this is necessary for resetting various parameters
340  needed for reopening and checking the file */
341  fd->newlyOpenedFile = TRUE;
342 
343  HDF5_CHECK(H5Pclose(createPropList),
344  "cannot close creation property list");
345  HDF5_CHECK(H5Pclose(accessPropList),
346  "cannot close access property list");
347 
348  /* create property list for serial/parallel access */
349  fd->xferPropList = H5Pcreate(H5P_DATASET_XFER);
350  HDF5_CHECK(fd->xferPropList, "cannot create transfer property list");
351 
352  /* set data transfer mode */
353  if (hints->collective) {
354  HDF5_CHECK(H5Pset_dxpl_mpio(fd->xferPropList, H5FD_MPIO_COLLECTIVE),
355  "cannot set collective data transfer mode");
356  } else {
357  HDF5_CHECK(H5Pset_dxpl_mpio
358  (fd->xferPropList, H5FD_MPIO_INDEPENDENT),
359  "cannot set independent data transfer mode");
360  }
361 
362  /* set up memory data space for transfer */
363  memStart[0] = (hsize_t) 0;
364  memCount[0] = (hsize_t) 1;
365  memStride[0] = (hsize_t) (hints->transferSize / sizeof(IOR_size_t));
366  memBlock[0] = (hsize_t) (hints->transferSize / sizeof(IOR_size_t));
367  memDataSpaceDims[0] = (hsize_t) hints->transferSize;
368  fd->memDataSpace = H5Screate_simple(NUM_DIMS, memDataSpaceDims, NULL);
369  HDF5_CHECK(fd->memDataSpace, "cannot create simple memory data space");
370 
371  /* define hyperslab for memory data space */
372  HDF5_CHECK(H5Sselect_hyperslab(fd->memDataSpace, H5S_SELECT_SET,
373  memStart, memStride, memCount,
374  memBlock), "cannot create hyperslab");
375 
376  /* set up parameters for fpp or different dataset count */
377  if (hints->filePerProc) {
378  tasksPerDataSet = 1;
379  } else {
380  if (o->individualDataSets) {
381  /* each task in segment has single data set */
382  tasksPerDataSet = 1;
383  } else {
384  /* share single data set across all tasks in segment */
385  tasksPerDataSet = hints->numTasks;
386  }
387  }
388  dataSetDims[0] = (hsize_t) ((hints->blockSize / sizeof(IOR_size_t))
389  * tasksPerDataSet);
390 
391  /* create a simple data space containing information on size
392  and shape of data set, and open it for access */
393  fd->dataSpace = H5Screate_simple(NUM_DIMS, dataSetDims, NULL);
394  HDF5_CHECK(fd->dataSpace, "cannot create simple data space");
395  if (mpiHints != MPI_INFO_NULL)
396  MPI_Info_free(&mpiHints);
397 
398  return (aiori_fd_t*)(fd);
399 }
400 
401 /*
402  * Write or read access to file using the HDF5 interface.
403  */
404 static IOR_offset_t HDF5_Xfer(int access, aiori_fd_t *afd, IOR_size_t * buffer,
405  IOR_offset_t length, IOR_offset_t offset, aiori_mod_opt_t * param)
406 {
407  IOR_offset_t segmentPosition, segmentSize;
408  aiori_h5fd_t * fd = (aiori_h5fd_t *) afd;
409 
410  /*
411  * this toggle is for the read check operation, which passes through
412  * this function twice; note that this function will open a data set
413  * only on the first read check and close only on the second
414  */
415  if (access == READCHECK) {
416  if (fd->firstReadCheck == TRUE) {
417  fd->firstReadCheck = FALSE;
418  } else {
419  fd->firstReadCheck = TRUE;
420  }
421  }
422 
423  /* determine by offset if need to start new data set */
424  if (hints->filePerProc == TRUE) {
425  segmentPosition = (IOR_offset_t) 0;
426  segmentSize = hints->blockSize;
427  } else {
428  segmentPosition =
429  (IOR_offset_t) ((rank + rankOffset) % hints->numTasks)
430  * hints->blockSize;
431  segmentSize = (IOR_offset_t) (hints->numTasks) * hints->blockSize;
432  }
433  if ((IOR_offset_t) ((offset - segmentPosition) % segmentSize) ==
434  0) {
435  /*
436  * ordinarily start a new data set, unless this is the
437  * second pass through during a read check
438  */
439  fd->startNewDataSet = TRUE;
440  if (access == READCHECK && fd->firstReadCheck != TRUE) {
441  fd->startNewDataSet = FALSE;
442  }
443  }
444 
445  if(hints->dryRun)
446  return length;
447 
448  /* create new data set */
449  if (fd->startNewDataSet == TRUE) {
450  /* if just opened this file, no data set to close yet */
451  if (fd->newlyOpenedFile != TRUE) {
452  HDF5_CHECK(H5Dclose(fd->dataSet), "cannot close data set");
453  HDF5_CHECK(H5Sclose(fd->fileDataSpace),
454  "cannot close file data space");
455  }
456  SetupDataSet(fd, access == WRITE ? IOR_CREAT : IOR_RDWR, param);
457  }
458 
459  SeekOffset(fd, offset, param);
460 
461  /* this is necessary to reset variables for reaccessing file */
462  fd->startNewDataSet = FALSE;
463  fd->newlyOpenedFile = FALSE;
464 
465  /* access the file */
466  if (access == WRITE) { /* WRITE */
467  HDF5_CHECK(H5Dwrite(fd->dataSet, H5T_NATIVE_LLONG,
468  fd->memDataSpace, fd->fileDataSpace,
469  fd->xferPropList, buffer),
470  "cannot write to data set");
471  } else { /* READ or CHECK */
472  HDF5_CHECK(H5Dread(fd->dataSet, H5T_NATIVE_LLONG,
473  fd->memDataSpace, fd->fileDataSpace,
474  fd->xferPropList, buffer),
475  "cannot read from data set");
476  }
477  return (length);
478 }
479 
480 /*
481  * Perform fsync().
482  */
483 static void HDF5_Fsync(aiori_fd_t *afd, aiori_mod_opt_t * param)
484 {
485  aiori_h5fd_t * fd = (aiori_h5fd_t *) afd;
486  HDF5_CHECK(H5Fflush(fd->fd, H5F_SCOPE_LOCAL), "cannot flush file to disk");
487 }
488 
489 /*
490  * Close a file through the HDF5 interface.
491  */
492 static void HDF5_Close(aiori_fd_t *afd, aiori_mod_opt_t * param)
493 {
494  aiori_h5fd_t * fd = (aiori_h5fd_t *) afd;
495  if(hints->dryRun)
496  return;
497  //if (hints->fd_fppReadCheck == NULL) {
498  HDF5_CHECK(H5Dclose(fd->dataSet), "cannot close data set");
499  HDF5_CHECK(H5Sclose(fd->dataSpace), "cannot close data space");
500  HDF5_CHECK(H5Sclose(fd->fileDataSpace),
501  "cannot close file data space");
502  HDF5_CHECK(H5Sclose(fd->memDataSpace),
503  "cannot close memory data space");
504  HDF5_CHECK(H5Pclose(fd->xferPropList),
505  " cannot close transfer property list");
506  //}
507  HDF5_CHECK(H5Fclose(fd->fd), "cannot close file");
508  free(fd);
509 }
510 
511 /*
512  * Delete a file through the HDF5 interface.
513  */
514 static void HDF5_Delete(char *testFileName, aiori_mod_opt_t * param)
515 {
516 #ifdef HAVE_H5FDELETE
517  hid_t accessPropList;
518  MPI_Comm comm = MPI_COMM_SELF; /* Ony one rank accesses the file */
519  MPI_Info mpiHints = MPI_INFO_NULL;
520 #endif
521 
522  if(hints->dryRun)
523  return;
524 
525 #ifdef HAVE_H5FDELETE
526  /* set up file access property list */
527  accessPropList = H5Pcreate(H5P_FILE_ACCESS);
528  HDF5_CHECK(accessPropList, "cannot create file access property list");
529 
530  HDF5_CHECK(H5Pset_fapl_mpio(accessPropList, comm, mpiHints),
531  "cannot set file access property list");
532 
533  HDF5_CHECK(H5Fdelete(testFileName, accessPropList),
534  "cannot delete file");
535 
536  HDF5_CHECK(H5Pclose(accessPropList),
537  "cannot close access property list");
538 #else
539  MPIIO_Delete(testFileName, NULL);
540 #endif
541 
542  return;
543 }
544 
545 /*
546  * Determine api version.
547  */
548 static char * HDF5_GetVersion()
549 {
550  static char version[1024] = {0};
551  if(version[0]) return version;
552 
553  unsigned major, minor, release;
554  if (H5get_libversion(&major, &minor, &release) < 0) {
555  WARN("cannot get HDF5 library version");
556  } else {
557  sprintf(version, "%u.%u.%u", major, minor, release);
558  }
559 #ifndef H5_HAVE_PARALLEL
560  strcat(version, " (Serial)");
561 #else /* H5_HAVE_PARALLEL */
562  strcat(version, " (Parallel)");
563 #endif /* not H5_HAVE_PARALLEL */
564  return version;
565 }
566 
567 /*
568  * Seek to offset in file using the HDF5 interface and set up hyperslab.
569  */
570 static IOR_offset_t SeekOffset(void *afd, IOR_offset_t offset,
571  aiori_mod_opt_t * param)
572 {
573  aiori_h5fd_t * fd = (aiori_h5fd_t *) afd;
574  HDF5_options_t *o = (HDF5_options_t*) param;
575  IOR_offset_t segmentSize;
576  hsize_t hsStride[NUM_DIMS], hsCount[NUM_DIMS], hsBlock[NUM_DIMS];
577  hsize_t hsStart[NUM_DIMS];
578 
579  if (hints->filePerProc == TRUE) {
580  segmentSize = (IOR_offset_t) hints->blockSize;
581  } else {
582  segmentSize = (IOR_offset_t) (hints->numTasks) * hints->blockSize;
583  }
584 
585  /* create a hyperslab representing the file data space */
586  if (o->individualDataSets) {
587  /* start at zero offset if not */
588  hsStart[0] = (hsize_t) ((offset % hints->blockSize) / sizeof(IOR_size_t));
589  } else {
590  /* start at a unique offset if shared */
591  hsStart[0] = (hsize_t) ((offset % segmentSize) / sizeof(IOR_size_t));
592  }
593  hsCount[0] = (hsize_t) 1;
594  hsStride[0] = (hsize_t) (hints->transferSize / sizeof(IOR_size_t));
595  hsBlock[0] = (hsize_t) (hints->transferSize / sizeof(IOR_size_t));
596 
597  /* select hyperslab in file data space */
598  HDF5_CHECK(H5Sselect_hyperslab(fd->fileDataSpace, H5S_SELECT_SET, hsStart, hsStride, hsCount, hsBlock),
599  "cannot select hyperslab");
600  return (offset);
601 }
602 
603 /*
604  * Create HDF5 data set.
605  */
606 static void SetupDataSet(aiori_h5fd_t *fd, int flags, aiori_mod_opt_t * param)
607 {
608 
609  HDF5_options_t *o = (HDF5_options_t*) param;
610  char dataSetName[MAX_STR];
611  hid_t dataSetPropList;
612  int dataSetID;
613  static int dataSetSuffix = 0;
614 
615  /* may want to use an extendable dataset (H5S_UNLIMITED) someday */
616 
617  /* need to reset suffix counter if newly-opened file */
618  if (fd->newlyOpenedFile)
619  dataSetSuffix = 0;
620 
621  /* may want to use individual access to each data set someday */
622  if (o->individualDataSets) {
623  dataSetID = (rank + rankOffset) % hints->numTasks;
624  } else {
625  dataSetID = 0;
626  }
627 
628  sprintf(dataSetName, "%s-%04d.%04d", "Dataset", dataSetID,
629  dataSetSuffix++);
630 
631  if (flags & IOR_CREAT) { /* WRITE */
632  hsize_t chunk_dims[NUM_DIMS];
633 
634  /* create data set */
635  dataSetPropList = H5Pcreate(H5P_DATASET_CREATE);
636 
637  /* Set chunk size */
638  if (o->chunk_size > 0) {
639  int i;
640 
641  for (i = 0; i < NUM_DIMS; i++)
642  chunk_dims[i] = o->chunk_size;
643 
644  HDF5_CHECK(H5Pset_chunk(dataSetPropList, NUM_DIMS, chunk_dims),
645  "cannot set chunk size");
646  }
647 
648  if (o->noFill == TRUE) {
649  if (rank == 0 && verbose >= VERBOSE_1) {
650  fprintf(stdout, "\nusing 'no fill' option\n");
651  }
652  HDF5_CHECK(H5Pset_fill_time(dataSetPropList,
653  H5D_FILL_TIME_NEVER),
654  "cannot set fill time for property list");
655  }
656  fd->dataSet = H5Dcreate(fd->fd, dataSetName, H5T_NATIVE_LLONG, fd->dataSpace, dataSetPropList);
657  HDF5_CHECK(fd->dataSet, "cannot create data set");
658  } else { /* READ or CHECK */
659  fd->dataSet = H5Dopen(*(hid_t *) fd, dataSetName);
660  HDF5_CHECK(fd->dataSet, "cannot open data set");
661  }
662 
663  /* retrieve data space from data set for hyperslab */
664  fd->fileDataSpace = H5Dget_space(fd->dataSet);
665  HDF5_CHECK(fd->fileDataSpace, "cannot get data space from data set");
666 }
667 
668 static IOR_offset_t HDF5_GetFileSize(aiori_mod_opt_t * test, char *testFileName)
669 {
670  /* Ensure that non-native VOLs do not use MPIIO_GetFileSize() */
671 #ifdef HAVE_H5PGET_VOL_ID
672  hid_t vol_id, accessPropList;
673 #endif
674  IOR_offset_t ret;
675 
676  if(hints->dryRun)
677  return 0;
678 
679 #ifdef HAVE_H5PGET_VOL_ID
680  /* set up file access property list */
681  accessPropList = H5Pcreate(H5P_FILE_ACCESS);
682  HDF5_CHECK(accessPropList, "cannot create file access property list");
683  HDF5_CHECK(H5Pget_vol_id(accessPropList, &vol_id), "cannot get vol id");
684  HDF5_CHECK(H5Pclose(accessPropList), "cannot close access property list");
685 
686  if(vol_id == H5VL_NATIVE)
687 #endif
688  ret = MPIIO_GetFileSize(test, testFileName);
689 #ifdef HAVE_H5PGET_VOL_ID
690  else {
691  if(rank == 0)
692  WARN("getfilesize not supported with current VOL connector!");
693 
694  ret = -1;
695  }
696 
697  HDF5_CHECK(H5VLclose(vol_id), "cannot close VOL ID");
698 #endif
699 
700  return ret;
701 }
702 
703 static int HDF5_StatFS(const char * oid, ior_aiori_statfs_t * stat_buf,
704  aiori_mod_opt_t * param)
705 {
706  int ret;
707 #ifdef HAVE_H5PGET_VOL_ID
708  hid_t vol_id, accessPropList;
709 
710  /* set up file access property list */
711  accessPropList = H5Pcreate(H5P_FILE_ACCESS);
712  HDF5_CHECK(accessPropList, "cannot create file access property list");
713  HDF5_CHECK(H5Pget_vol_id(accessPropList, &vol_id), "cannot get vol id");
714  HDF5_CHECK(H5Pclose(accessPropList), "cannot close access property list");
715 
716  if(vol_id == H5VL_NATIVE)
717 #endif
718  ret = aiori_posix_statfs(oid, stat_buf, param);
719 #ifdef HAVE_H5PGET_VOL_ID
720  else {
721  if(rank == 0)
722  WARN("statfs not supported by current VOL connector!");
723 
724  ret = -1;
725  }
726 
727  HDF5_CHECK(H5VLclose(vol_id), "cannot close VOL ID");
728 #endif
729 
730  return ret;
731 }
732 
733 static int HDF5_MkDir(const char * oid, mode_t mode, aiori_mod_opt_t * param)
734 {
735  int ret;
736 #ifdef HAVE_H5PGET_VOL_ID
737  hid_t vol_id, accessPropList;
738 
739  /* set up file access property list */
740  accessPropList = H5Pcreate(H5P_FILE_ACCESS);
741  HDF5_CHECK(accessPropList, "cannot create file access property list");
742  HDF5_CHECK(H5Pget_vol_id(accessPropList, &vol_id), "cannot get vol id");
743  HDF5_CHECK(H5Pclose(accessPropList), "cannot close access property list");
744 
745  if(vol_id == H5VL_NATIVE)
746 #endif
747  ret = aiori_posix_mkdir(oid, mode, param);
748 #ifdef HAVE_H5PGET_VOL_ID
749  else {
750  if(rank == 0)
751  WARN("mkdir not supported by current VOL connector!");
752 
753  ret = -1;
754  }
755 
756  HDF5_CHECK(H5VLclose(vol_id), "cannot close VOL ID");
757 #endif
758 
759  return ret;
760 }
761 
762 static int HDF5_RmDir(const char * oid, aiori_mod_opt_t * param)
763 {
764  int ret;
765 #ifdef HAVE_H5PGET_VOL_ID
766  hid_t vol_id, accessPropList;
767 
768  /* set up file access property list */
769  accessPropList = H5Pcreate(H5P_FILE_ACCESS);
770  HDF5_CHECK(accessPropList, "cannot create file access property list");
771  HDF5_CHECK(H5Pget_vol_id(accessPropList, &vol_id), "cannot get vol id");
772  HDF5_CHECK(H5Pclose(accessPropList), "cannot close access property list");
773 
774  if(vol_id == H5VL_NATIVE)
775 #endif
776  ret = aiori_posix_rmdir(oid, param);
777 #ifdef HAVE_H5PGET_VOL_ID
778  else {
779  if(rank == 0)
780  WARN("rmdir not supported by current VOL connector!");
781 
782  ret = -1;
783  }
784 
785  HDF5_CHECK(H5VLclose(vol_id), "cannot close VOL ID");
786 #endif
787 
788  return ret;
789 }
790 
791 static int HDF5_Access(const char * path, int mode, aiori_mod_opt_t * param)
792 {
793  htri_t accessible = -1;
794  hid_t accessPropList;
795  MPI_Comm comm = MPI_COMM_SELF; /* Ony one rank accesses the file */
796  MPI_Info mpiHints = MPI_INFO_NULL;
797  int ret = -1;
798 
799  if(hints->dryRun)
800  return 0;
801 
802 #ifdef HAVE_H5FIS_ACCESSIBLE
803  /* set up file access property list */
804  accessPropList = H5Pcreate(H5P_FILE_ACCESS);
805  HDF5_CHECK(accessPropList, "cannot create file access property list");
806 
807  HDF5_CHECK(H5Pset_fapl_mpio(accessPropList, comm, mpiHints),
808  "cannot set file access property list");
809 
810  H5E_BEGIN_TRY {
811  accessible = H5Fis_accessible(path, accessPropList);
812  } H5E_END_TRY;
813  if (accessible > 0)
814  ret = 0;
815 
816  HDF5_CHECK(H5Pclose(accessPropList),
817  "cannot close access property list");
818 #else
819  ret = MPIIO_Access(path, mode, param);
820 #endif
821 
822  return ret;
823 }
824 
825 static int HDF5_Stat(const char * oid, struct stat * buf, aiori_mod_opt_t * param)
826 {
827  int ret;
828 #ifdef HAVE_H5PGET_VOL_ID
829  hid_t vol_id, accessPropList;
830 
831  /* set up file access property list */
832  accessPropList = H5Pcreate(H5P_FILE_ACCESS);
833  HDF5_CHECK(accessPropList, "cannot create file access property list");
834  HDF5_CHECK(H5Pget_vol_id(accessPropList, &vol_id), "cannot get vol id");
835  HDF5_CHECK(H5Pclose(accessPropList), "cannot close access property list");
836 
837  if(vol_id == H5VL_NATIVE)
838 #endif
839  ret = aiori_posix_stat(oid, buf, param);
840 #ifdef HAVE_H5PGET_VOL_ID
841  else {
842  if(rank == 0)
843  WARN("stat not supported by current VOL connector!");
844 
845  ret = -1;
846  }
847 
848  HDF5_CHECK(H5VLclose(vol_id), "cannot close VOL ID");
849 #endif
850 
851  return ret;
852 }
853 
854 /*
855  * Call H5close to ensure library is
856  * shutdown before MPI_Finalize is called
857  */
858 static void
860 {
861  H5close();
862 }
hid_t dataSet
Definition: aiori-HDF5.c:178
static aiori_fd_t * HDF5_Create(char *, int flags, aiori_mod_opt_t *)
Definition: aiori-HDF5.c:210
static void HDF5_init_xfer_options(aiori_xfer_hint_t *params)
Definition: aiori-HDF5.c:192
void ShowHints(MPI_Info *mpiHints)
Definition: utilities.c:717
static void HDF5_Close(aiori_fd_t *, aiori_mod_opt_t *)
Definition: aiori-HDF5.c:492
static int HDF5_MkDir(const char *, mode_t, aiori_mod_opt_t *)
Definition: aiori-HDF5.c:733
#define LAST_OPTION
Definition: option.h:39
int firstReadCheck
Definition: aiori-HDF5.c:183
static void SetupDataSet(aiori_h5fd_t *, int flags, aiori_mod_opt_t *)
Definition: aiori-HDF5.c:606
struct benchmark_options o
Definition: md-workbench.c:133
IOR_offset_t blockSize
Definition: aiori.h:72
hid_t memDataSpace
Definition: aiori-HDF5.c:181
ior_aiori_t hdf5_aiori
Definition: aiori-HDF5.c:153
#define READCHECK
Definition: iordef.h:103
#define HDF5_CHECK(HDF5_RETURN, MSG)
Definition: aiori-HDF5.c:68
int showHints
Definition: aiori.h:165
#define IOR_APPEND
Definition: aiori.h:31
IOR_offset_t MPIIO_GetFileSize(aiori_mod_opt_t *module_options, char *testFileName)
Definition: aiori-MPIIO.c:579
#define IOR_RDONLY
Definition: aiori.h:28
hid_t xferPropList
Definition: aiori-HDF5.c:177
IOR_offset_t setAlignment
Definition: aiori-HDF5.c:112
#define MPI_CHECK(MPI_STATUS, MSG)
Definition: aiori-debug.h:97
#define WRITE
Definition: iordef.h:100
#define NUM_DIMS
Definition: aiori-HDF5.c:32
int aiori_posix_stat(const char *path, struct stat *buf, aiori_mod_opt_t *module_options)
Definition: aiori.c:230
static aiori_xfer_hint_t * hints
Definition: aiori-HDF5.c:190
static option_help * HDF5_options(aiori_mod_opt_t **init_backend_options, aiori_mod_opt_t *init_values)
Definition: aiori-HDF5.c:117
#define IOR_CREAT
Definition: aiori.h:32
static int HDF5_RmDir(const char *, aiori_mod_opt_t *)
Definition: aiori-HDF5.c:762
static int HDF5_Access(const char *, int, aiori_mod_opt_t *)
Definition: aiori-HDF5.c:791
#define IOR_EXCL
Definition: aiori.h:34
static int HDF5_Stat(const char *, struct stat *, aiori_mod_opt_t *)
Definition: aiori-HDF5.c:825
int MPIIO_Access(const char *path, int mode, aiori_mod_opt_t *module_options)
Definition: aiori-MPIIO.c:130
int individualDataSets
Definition: aiori-HDF5.c:110
MPI_Comm testComm
Definition: utilities.c:73
static option_help options[]
Definition: aiori-CEPHFS.c:59
#define IOR_TRUNC
Definition: aiori.h:33
#define WARN(MSG)
Definition: aiori-debug.h:45
int collective
Definition: aiori.h:66
static void HDF5_Fsync(aiori_fd_t *, aiori_mod_opt_t *)
Definition: aiori-HDF5.c:483
static int HDF5_check_params(aiori_mod_opt_t *options)
Definition: aiori-HDF5.c:198
void MPIIO_xfer_hints(aiori_xfer_hint_t *params)
Definition: aiori-MPIIO.c:102
int startNewDataSet
Definition: aiori-HDF5.c:184
char * hintsFileName
Definition: aiori.h:170
IOR_offset_t transferSize
Definition: aiori.h:73
static void HDF5_Finalize(aiori_mod_opt_t *)
Definition: aiori-HDF5.c:859
static void HDF5_Delete(char *, aiori_mod_opt_t *)
Definition: aiori-HDF5.c:514
#define IOR_WRONLY
Definition: aiori.h:29
static char * HDF5_GetVersion()
Definition: aiori-HDF5.c:548
#define FALSE
Definition: iordef.h:76
int rankOffset
Definition: utilities.c:71
long long int IOR_size_t
Definition: iordef.h:124
int aiori_posix_rmdir(const char *path, aiori_mod_opt_t *module_options)
Definition: aiori.c:220
static aiori_fd_t * HDF5_Open(char *, int flags, aiori_mod_opt_t *)
Definition: aiori-HDF5.c:218
hid_t dataSpace
Definition: aiori-HDF5.c:179
int aiori_posix_mkdir(const char *path, mode_t mode, aiori_mod_opt_t *module_options)
Definition: aiori.c:215
hid_t fileDataSpace
Definition: aiori-HDF5.c:180
static IOR_offset_t HDF5_Xfer(int, aiori_fd_t *, IOR_size_t *, IOR_offset_t, IOR_offset_t, aiori_mod_opt_t *)
Definition: aiori-HDF5.c:404
int verbose
Definition: utilities.c:72
#define MAX_STR
Definition: iordef.h:113
int newlyOpenedFile
Definition: aiori-HDF5.c:182
int aiori_posix_statfs(const char *path, ior_aiori_statfs_t *stat_buf, aiori_mod_opt_t *module_options)
Definition: aiori.c:169
void SetHints(MPI_Info *mpiHints, char *hintsFileName)
Definition: utilities.c:656
static int HDF5_StatFS(const char *, ior_aiori_statfs_t *, aiori_mod_opt_t *)
Definition: aiori-HDF5.c:703
mpiio_options_t mpio
Definition: aiori-HDF5.c:107
#define ERR(MSG)
Definition: aiori-debug.h:75
#define IOR_RDWR
Definition: aiori.h:30
void MPIIO_Delete(char *testFileName, aiori_mod_opt_t *module_options)
Definition: aiori-MPIIO.c:512
#define VERBOSE_1
Definition: iordef.h:107
char * name
Definition: aiori.h:88
static IOR_offset_t HDF5_GetFileSize(aiori_mod_opt_t *, char *)
Definition: aiori-HDF5.c:668
int filePerProc
Definition: aiori.h:65
long long int IOR_offset_t
Definition: iordef.h:123
int rank
Definition: utilities.c:70
#define TRUE
Definition: iordef.h:80
#define IOR_DIRECT
Definition: aiori.h:35
void * safeMalloc(uint64_t size)
Definition: utilities.c:238
#define NULL
Definition: iordef.h:84
static IOR_offset_t SeekOffset(void *, IOR_offset_t, aiori_mod_opt_t *)
Definition: aiori-HDF5.c:570