ESScript  Revision_
esysFileWriter.h
Go to the documentation of this file.
1 
2 /*****************************************************************************
3 *
4 * Copyright (c) 2003-2013 by University of Queensland
5 * http://www.uq.edu.au
6 *
7 * Primary Business: Queensland, Australia
8 * Licensed under the Open Software License version 3.0
9 * http://www.opensource.org/licenses/osl-3.0.php
10 *
11 * Development until 2012 by Earth Systems Science Computational Center (ESSCC)
12 * Development since 2012 by School of Earth Sciences
13 *
14 *****************************************************************************/
15 
16 #ifndef __ESYS_FILEWRITER_H__
17 #define __ESYS_FILEWRITER_H__
18 
19 #include <fstream>
20 #include <iostream>
21 #include <sstream>
22 
23 #ifdef ESYS_MPI
24 #include <mpi.h>
25 #endif
26 
27 namespace esysUtils {
28 
30 {
31 public:
32  FileWriter() : mpiRank(0), mpiSize(1) {}
33 
34 #ifdef ESYS_MPI
35  FileWriter(MPI_Comm comm) : mpiComm(comm)
36  {
37  MPI_Comm_rank(mpiComm, &mpiRank);
38  MPI_Comm_size(mpiComm, &mpiSize);
39  }
40 #endif
41 
42  bool openFile(std::string filename, size_t initialSize=0)
43  {
44  bool success=false;
45 
46  if (mpiSize>1) {
47 #ifdef ESYS_MPI
48  // remove file first if it exists
49  int error = 0;
50  int mpiErr;
51  if (mpiRank == 0) {
52  std::ifstream f(filename.c_str());
53  if (f.is_open()) {
54  f.close();
55  if (std::remove(filename.c_str())) {
56  error=1;
57  }
58  }
59  }
60  MPI_Allreduce(&error, &mpiErr, 1, MPI_INT, MPI_MAX, mpiComm);
61  if (mpiErr != 0) {
62  std::cerr << "Error removing " << filename << "!" << std::endl;
63  return false;
64  }
65 
66  MPI_Info mpiInfo = MPI_INFO_NULL;
67  int amode = MPI_MODE_CREATE|MPI_MODE_WRONLY|MPI_MODE_UNIQUE_OPEN;
68  mpiErr = MPI_File_open(mpiComm, const_cast<char*>(filename.c_str()),
69  amode, mpiInfo, &fileHandle);
70  if (mpiErr == MPI_SUCCESS) {
71  mpiErr = MPI_File_set_view(fileHandle, 0, MPI_CHAR, MPI_CHAR,
72  const_cast<char*>("native"), mpiInfo);
73  }
74  if (mpiErr == MPI_SUCCESS) {
75  mpiErr = MPI_File_set_size(fileHandle, initialSize);
76  }
77  if (mpiErr != MPI_SUCCESS) {
78  std::cerr << "Error opening " << filename << " for parallel writing!" << std::endl;
79  } else {
80  success=true;
81  }
82 #endif
83  } else {
84  std::ios_base::openmode mode = std::ios_base::binary;
85  ofs.open(filename.c_str(), mode);
86  success = !ofs.fail();
87  if (success && initialSize>0) {
88  ofs.seekp(initialSize-1, ofs.beg).put(0).seekp(0, ofs.beg);
89  success = !ofs.fail();
90  }
91  }
92  return success;
93  }
94 
95  bool writeOrdered(std::ostringstream& oss)
96  {
97  bool success=false;
98  if (mpiSize>1) {
99 #ifdef ESYS_MPI
100  MPI_Status mpiStatus;
101  std::string contents = oss.str();
102  int mpiErr = MPI_File_write_ordered(
103  fileHandle, const_cast<char*>(contents.c_str()),
104  contents.length(), MPI_CHAR, &mpiStatus);
105  oss.str(std::string());
106  success=(mpiErr==0);
107 #endif
108  } else {
109  ofs << oss.str();
110  oss.str(std::string());
111  success=!ofs.fail();
112  }
113  return success;
114  }
115 
116  bool writeShared(std::ostringstream& oss)
117  {
118  bool success=false;
119  if (mpiSize>1) {
120 #ifdef ESYS_MPI
121  MPI_Status mpiStatus;
122  std::string contents = oss.str();
123  int mpiErr = MPI_File_write_shared(
124  fileHandle, const_cast<char*>(contents.c_str()),
125  contents.length(), MPI_CHAR, &mpiStatus);
126  oss.str(std::string());
127  success=(mpiErr==0);
128 #endif
129  } else {
130  ofs << oss.str();
131  oss.str(std::string());
132  success=!ofs.fail();
133  }
134  return success;
135  }
136 
137  bool writeAt(std::ostringstream& oss, long offset)
138  {
139  bool success=false;
140  if (mpiSize>1) {
141 #ifdef ESYS_MPI
142  MPI_Status mpiStatus;
143  std::string contents = oss.str();
144  int mpiErr = MPI_File_write_at(
145  fileHandle, offset, const_cast<char*>(contents.c_str()),
146  contents.length(), MPI_CHAR, &mpiStatus);
147  oss.str(std::string());
148  success=(mpiErr==0);
149 #endif
150  } else {
151  ofs.seekp(offset);
152  ofs << oss.str();
153  oss.str(std::string());
154  success=!ofs.fail();
155  }
156  return success;
157  }
158 
159  void close()
160  {
161  if (mpiSize>1) {
162 #ifdef ESYS_MPI
163  MPI_File_close(&fileHandle);
164 #endif
165  } else {
166  ofs.close();
167  }
168  }
169 
170 private:
172 #ifdef ESYS_MPI
174  MPI_File fileHandle;
175 #else
176  void* mpiComm;
177 #endif
178  std::ofstream ofs;
179 };
180 
181 
182 } // namespace esysUtils
183 
184 #endif // __ESYS_FILEWRITER_H__
185