escript  Revision_4925
esysFileWriter.h
Go to the documentation of this file.
1 
2 /*****************************************************************************
3 *
4 * Copyright (c) 2003-2014 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 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 #ifdef ESYS_MPI
25 #include <mpi.h>
26 #endif
27 
28 namespace esysUtils {
29 
31 {
32 public:
33  FileWriter() : mpiRank(0), mpiSize(1) {}
34 
35 #ifdef ESYS_MPI
36  FileWriter(MPI_Comm comm) : mpiComm(comm)
37  {
38  MPI_Comm_rank(mpiComm, &mpiRank);
39  MPI_Comm_size(mpiComm, &mpiSize);
40  }
41 #endif
42 
43  bool openFile(std::string filename, size_t initialSize=0)
44  {
45  bool success=false;
46 
47  if (mpiSize>1) {
48 #ifdef ESYS_MPI
49  // remove file first if it exists
50  int error = 0;
51  int mpiErr;
52  if (mpiRank == 0) {
53  std::ifstream f(filename.c_str());
54  if (f.is_open()) {
55  f.close();
56  if (std::remove(filename.c_str())) {
57  error=1;
58  }
59  }
60  }
61  MPI_Allreduce(&error, &mpiErr, 1, MPI_INT, MPI_MAX, mpiComm);
62  if (mpiErr != 0) {
63  std::cerr << "Error removing " << filename << "!" << std::endl;
64  return false;
65  }
66 
67  MPI_Info mpiInfo = MPI_INFO_NULL;
68  int amode = MPI_MODE_CREATE|MPI_MODE_WRONLY|MPI_MODE_UNIQUE_OPEN;
69  mpiErr = MPI_File_open(mpiComm, const_cast<char*>(filename.c_str()),
70  amode, mpiInfo, &fileHandle);
71  if (mpiErr == MPI_SUCCESS) {
72  mpiErr = MPI_File_set_view(fileHandle, 0, MPI_CHAR, MPI_CHAR,
73  const_cast<char*>("native"), mpiInfo);
74  }
75  if (mpiErr == MPI_SUCCESS) {
76  mpiErr = MPI_File_set_size(fileHandle, initialSize);
77  }
78  if (mpiErr != MPI_SUCCESS) {
79  std::cerr << "Error opening " << filename << " for parallel writing!" << std::endl;
80  } else {
81  success=true;
82  }
83 #endif
84  } else {
85  std::ios_base::openmode mode = std::ios_base::binary;
86  ofs.open(filename.c_str(), mode);
87  success = !ofs.fail();
88  if (success && initialSize>0) {
89  ofs.seekp(initialSize-1, ofs.beg).put(0).seekp(0, ofs.beg);
90  success = !ofs.fail();
91  }
92  }
93  return success;
94  }
95 
96  bool writeOrdered(std::ostringstream& oss)
97  {
98  bool success=false;
99  if (mpiSize>1) {
100 #ifdef ESYS_MPI
101  MPI_Status mpiStatus;
102  std::string contents = oss.str();
103  int mpiErr = MPI_File_write_ordered(
104  fileHandle, const_cast<char*>(contents.c_str()),
105  contents.length(), MPI_CHAR, &mpiStatus);
106  oss.str(std::string());
107  success=(mpiErr==0);
108 #endif
109  } else {
110  ofs << oss.str();
111  oss.str(std::string());
112  success=!ofs.fail();
113  }
114  return success;
115  }
116 
117  bool writeShared(std::ostringstream& oss)
118  {
119  bool success=false;
120  if (mpiSize>1) {
121 #ifdef ESYS_MPI
122  MPI_Status mpiStatus;
123  std::string contents = oss.str();
124  int mpiErr = MPI_File_write_shared(
125  fileHandle, const_cast<char*>(contents.c_str()),
126  contents.length(), MPI_CHAR, &mpiStatus);
127  oss.str(std::string());
128  success=(mpiErr==0);
129 #endif
130  } else {
131  ofs << oss.str();
132  oss.str(std::string());
133  success=!ofs.fail();
134  }
135  return success;
136  }
137 
138  bool writeAt(std::ostringstream& oss, long offset)
139  {
140  bool success=false;
141  if (mpiSize>1) {
142 #ifdef ESYS_MPI
143  MPI_Status mpiStatus;
144  std::string contents = oss.str();
145  int mpiErr = MPI_File_write_at(
146  fileHandle, offset, const_cast<char*>(contents.c_str()),
147  contents.length(), MPI_CHAR, &mpiStatus);
148  oss.str(std::string());
149  success=(mpiErr==0);
150 #endif
151  } else {
152  ofs.seekp(offset);
153  ofs << oss.str();
154  oss.str(std::string());
155  success=!ofs.fail();
156  }
157  return success;
158  }
159 
160  void close()
161  {
162  if (mpiSize>1) {
163 #ifdef ESYS_MPI
164  MPI_File_close(&fileHandle);
165 #endif
166  } else {
167  ofs.close();
168  }
169  }
170 
171 private:
173 #ifdef ESYS_MPI
175  MPI_File fileHandle;
176 #else
177  void* mpiComm;
178 #endif
179  std::ofstream ofs;
180 };
181 
182 
183 } // namespace esysUtils
184 
185 #endif // __ESYS_FILEWRITER_H__
186 
FileWriter()
Definition: esysFileWriter.h:33
int mpiRank
Definition: esysFileWriter.h:172
bool writeOrdered(std::ostringstream &oss)
Definition: esysFileWriter.h:96
#define MPI_INT
Definition: Esys_MPI.h:32
bool openFile(std::string filename, size_t initialSize=0)
Definition: esysFileWriter.h:43
int MPI_Comm
Definition: Esys_MPI.h:29
bool writeAt(std::ostringstream &oss, long offset)
Definition: esysFileWriter.h:138
Definition: esysFileWriter.h:30
int mpiSize
Definition: esysFileWriter.h:172
int MPI_Status
Definition: Esys_MPI.h:31
void close()
Definition: esysFileWriter.h:160
void * mpiComm
Definition: esysFileWriter.h:177
bool writeShared(std::ostringstream &oss)
Definition: esysFileWriter.h:117
std::ofstream ofs
Definition: esysFileWriter.h:179