escript  Revision_
FileWriter.h
Go to the documentation of this file.
1 
2 /*****************************************************************************
3 *
4 * Copyright (c) 2003-2020 by The University of Queensland
5 * http://www.uq.edu.au
6 *
7 * Primary Business: Queensland, Australia
8 * Licensed under the Apache License, version 2.0
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Development until 2012 by Earth Systems Science Computational Center (ESSCC)
12 * Development 2012-2013 by School of Earth Sciences
13 * Development from 2014-2017 by Centre for Geoscience Computing (GeoComp)
14 * Development from 2019 by School of Earth and Environmental Sciences
15 **
16 *****************************************************************************/
17 
18 #ifndef __ESCRIPT_FILEWRITER_H__
19 #define __ESCRIPT_FILEWRITER_H__
20 
21 #include <escript/EsysMPI.h>
22 
23 #include <fstream>
24 #include <iostream>
25 #include <sstream>
26 
27 namespace escript {
28 
30 {
31 public:
33  mpiComm(comm), mpiRank(0), mpiSize(1), m_open(false)
34  {
35 #ifdef ESYS_MPI
36  if (comm != MPI_COMM_NULL) {
37  MPI_Comm_rank(mpiComm, &mpiRank);
38  MPI_Comm_size(mpiComm, &mpiSize);
39  }
40 #endif
41  }
42 
44  {
45  if (m_open)
46  close();
47  }
48 
49  bool openFile(std::string filename, size_t initialSize=0,
50  bool binary=false, bool append=false)
51  {
52  // close any open file first
53  if (m_open)
54  close();
55 
56  bool success=false;
57 
58  if (mpiSize > 1) {
59 #ifdef ESYS_MPI
60  int mpiErr;
61  if (!append) {
62  // remove file first if it exists
63  int error = 0;
64  if (mpiRank == 0) {
65  std::ifstream f(filename.c_str());
66  if (f.is_open()) {
67  f.close();
68  if (std::remove(filename.c_str())) {
69  error=1;
70  }
71  }
72  }
73  MPI_Allreduce(&error, &mpiErr, 1, MPI_INT, MPI_MAX, mpiComm);
74  if (mpiErr != 0) {
75  std::cerr << "Error removing " << filename << "!"
76  << std::endl;
77  return false;
78  }
79  }
80 
81  MPI_Info mpiInfo = MPI_INFO_NULL;
82  int amode = MPI_MODE_CREATE|MPI_MODE_WRONLY|MPI_MODE_UNIQUE_OPEN;
83  if (append)
84  amode |= MPI_MODE_APPEND;
85 
86  mpiErr = MPI_File_open(mpiComm, const_cast<char*>(filename.c_str()),
87  amode, mpiInfo, &fileHandle);
88  if (mpiErr == MPI_SUCCESS) {
89  mpiErr = MPI_File_set_view(fileHandle, 0, MPI_CHAR, MPI_CHAR,
90  const_cast<char*>("native"), mpiInfo);
91  }
92  if (mpiErr == MPI_SUCCESS) {
93  if (append) {
94  mpiErr = MPI_File_seek_shared(fileHandle, 0, MPI_SEEK_END);
95  } else {
96  mpiErr = MPI_File_set_size(fileHandle, initialSize);
97  }
98  }
99  if (mpiErr != MPI_SUCCESS) {
100  char errorstr[MPI_MAX_ERROR_STRING];
101  int len;
102  MPI_Error_string(mpiErr, errorstr, &len);
103  std::cerr << "Error opening " << filename
104  << " for parallel writing: " << errorstr << std::endl;
105  } else {
106  success=true;
107  }
108 #endif
109  } else {
110  std::ios_base::openmode mode =
111  (binary ? std::ios_base::binary : std::ios_base::out);
112  if (append)
113  mode |= std::ios_base::app;
114 
115  ofs.open(filename.c_str(), mode);
116  success = !ofs.fail();
117  if (success && initialSize>0 && !append) {
118  ofs.seekp(initialSize-1, ofs.beg).put(0).seekp(0, ofs.beg);
119  success = !ofs.fail();
120  }
121  }
122  m_open = success;
123  return success;
124  }
125 
126  bool writeOrdered(std::ostringstream& oss)
127  {
128  if (!m_open)
129  return false;
130 
131  bool success=false;
132  if (mpiSize>1) {
133 #ifdef ESYS_MPI
134  MPI_Status mpiStatus;
135  std::string contents = oss.str();
136  int mpiErr = MPI_File_write_ordered(
137  fileHandle, const_cast<char*>(contents.c_str()),
138  contents.length(), MPI_CHAR, &mpiStatus);
139  oss.str(std::string());
140  success=(mpiErr==0);
141 #endif
142  } else {
143  ofs << oss.str();
144  oss.str(std::string());
145  success=!ofs.fail();
146  }
147  return success;
148  }
149 
150  bool writeShared(std::ostringstream& oss)
151  {
152  if (!m_open)
153  return false;
154 
155  bool success=false;
156  if (mpiSize>1) {
157 #ifdef ESYS_MPI
158  MPI_Status mpiStatus;
159  std::string contents = oss.str();
160  int mpiErr = MPI_File_write_shared(
161  fileHandle, const_cast<char*>(contents.c_str()),
162  contents.length(), MPI_CHAR, &mpiStatus);
163  oss.str(std::string());
164  success=(mpiErr==0);
165 #endif
166  } else {
167  ofs << oss.str();
168  oss.str(std::string());
169  success=!ofs.fail();
170  }
171  return success;
172  }
173 
174  bool writeAt(std::ostringstream& oss, long offset)
175  {
176  if (!m_open)
177  return false;
178 
179  bool success=false;
180  if (mpiSize>1) {
181 #ifdef ESYS_MPI
182  MPI_Status mpiStatus;
183  std::string contents = oss.str();
184  int mpiErr = MPI_File_write_at(
185  fileHandle, offset, const_cast<char*>(contents.c_str()),
186  contents.length(), MPI_CHAR, &mpiStatus);
187  oss.str(std::string());
188  success=(mpiErr==0);
189 #endif
190  } else {
191  ofs.seekp(offset);
192  ofs << oss.str();
193  oss.str(std::string());
194  success=!ofs.fail();
195  }
196  return success;
197  }
198 
199  void close()
200  {
201  if (!m_open)
202  return;
203 
204  if (mpiSize>1) {
205 #ifdef ESYS_MPI
206  MPI_File_close(&fileHandle);
207 #endif
208  } else {
209  ofs.close();
210  }
211  m_open = false;
212  }
213 
214 private:
215 #pragma clang diagnostic push
216 #pragma clang diagnostic ignored "-Wunused-private-field"
218  int mpiRank;
219 #pragma clang diagnostic pop
220  int mpiSize;
221  bool m_open;
222 #ifdef ESYS_MPI
223  MPI_File fileHandle;
224 #endif
225  std::ofstream ofs;
226 };
227 
228 
229 } // namespace escript
230 
231 #endif // __ESCRIPT_FILEWRITER_H__
232 
#define MPI_COMM_NULL
Definition: EsysMPI.h:51
#define MPI_INT
Definition: EsysMPI.h:48
int MPI_Comm
Definition: EsysMPI.h:44
int MPI_Status
Definition: EsysMPI.h:47
#define MPI_MAX
Definition: EsysMPI.h:56
Definition: FileWriter.h:30
bool writeOrdered(std::ostringstream &oss)
Definition: FileWriter.h:126
FileWriter(MPI_Comm comm=MPI_COMM_NULL)
Definition: FileWriter.h:32
void close()
Definition: FileWriter.h:199
bool writeAt(std::ostringstream &oss, long offset)
Definition: FileWriter.h:174
bool writeShared(std::ostringstream &oss)
Definition: FileWriter.h:150
bool m_open
Definition: FileWriter.h:221
std::ofstream ofs
Definition: FileWriter.h:225
int mpiSize
Definition: FileWriter.h:220
~FileWriter()
Definition: FileWriter.h:43
int mpiRank
Definition: FileWriter.h:218
bool openFile(std::string filename, size_t initialSize=0, bool binary=false, bool append=false)
Definition: FileWriter.h:49
MPI_Comm mpiComm
Definition: FileWriter.h:217
Definition: AbstractContinuousDomain.cpp:23