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
27namespace escript {
28
30{
31public:
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
214private:
215#pragma clang diagnostic push
216#pragma clang diagnostic ignored "-Wunused-private-field"
219#pragma clang diagnostic pop
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