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