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