escript
Revision_
|
00001 00002 /***************************************************************************** 00003 * 00004 * Copyright (c) 2003-2014 by University of Queensland 00005 * http://www.uq.edu.au 00006 * 00007 * Primary Business: Queensland, Australia 00008 * Licensed under the Open Software License version 3.0 00009 * http://www.opensource.org/licenses/osl-3.0.php 00010 * 00011 * Development until 2012 by Earth Systems Science Computational Center (ESSCC) 00012 * Development 2012-2013 by School of Earth Sciences 00013 * Development from 2014 by Centre for Geoscience Computing (GeoComp) 00014 * 00015 *****************************************************************************/ 00016 00017 #ifndef __ESYS_FILEWRITER_H__ 00018 #define __ESYS_FILEWRITER_H__ 00019 00020 #include <fstream> 00021 #include <iostream> 00022 #include <sstream> 00023 00024 #ifdef ESYS_MPI 00025 #include <mpi.h> 00026 #endif 00027 00028 namespace esysUtils { 00029 00030 class FileWriter 00031 { 00032 public: 00033 FileWriter() : mpiRank(0), mpiSize(1) {} 00034 00035 #ifdef ESYS_MPI 00036 FileWriter(MPI_Comm comm) : mpiComm(comm) 00037 { 00038 MPI_Comm_rank(mpiComm, &mpiRank); 00039 MPI_Comm_size(mpiComm, &mpiSize); 00040 } 00041 #endif 00042 00043 bool openFile(std::string filename, size_t initialSize=0) 00044 { 00045 bool success=false; 00046 00047 if (mpiSize>1) { 00048 #ifdef ESYS_MPI 00049 // remove file first if it exists 00050 int error = 0; 00051 int mpiErr; 00052 if (mpiRank == 0) { 00053 std::ifstream f(filename.c_str()); 00054 if (f.is_open()) { 00055 f.close(); 00056 if (std::remove(filename.c_str())) { 00057 error=1; 00058 } 00059 } 00060 } 00061 MPI_Allreduce(&error, &mpiErr, 1, MPI_INT, MPI_MAX, mpiComm); 00062 if (mpiErr != 0) { 00063 std::cerr << "Error removing " << filename << "!" << std::endl; 00064 return false; 00065 } 00066 00067 MPI_Info mpiInfo = MPI_INFO_NULL; 00068 int amode = MPI_MODE_CREATE|MPI_MODE_WRONLY|MPI_MODE_UNIQUE_OPEN; 00069 mpiErr = MPI_File_open(mpiComm, const_cast<char*>(filename.c_str()), 00070 amode, mpiInfo, &fileHandle); 00071 if (mpiErr == MPI_SUCCESS) { 00072 mpiErr = MPI_File_set_view(fileHandle, 0, MPI_CHAR, MPI_CHAR, 00073 const_cast<char*>("native"), mpiInfo); 00074 } 00075 if (mpiErr == MPI_SUCCESS) { 00076 mpiErr = MPI_File_set_size(fileHandle, initialSize); 00077 } 00078 if (mpiErr != MPI_SUCCESS) { 00079 std::cerr << "Error opening " << filename << " for parallel writing!" << std::endl; 00080 } else { 00081 success=true; 00082 } 00083 #endif 00084 } else { 00085 std::ios_base::openmode mode = std::ios_base::binary; 00086 ofs.open(filename.c_str(), mode); 00087 success = !ofs.fail(); 00088 if (success && initialSize>0) { 00089 ofs.seekp(initialSize-1, ofs.beg).put(0).seekp(0, ofs.beg); 00090 success = !ofs.fail(); 00091 } 00092 } 00093 return success; 00094 } 00095 00096 bool writeOrdered(std::ostringstream& oss) 00097 { 00098 bool success=false; 00099 if (mpiSize>1) { 00100 #ifdef ESYS_MPI 00101 MPI_Status mpiStatus; 00102 std::string contents = oss.str(); 00103 int mpiErr = MPI_File_write_ordered( 00104 fileHandle, const_cast<char*>(contents.c_str()), 00105 contents.length(), MPI_CHAR, &mpiStatus); 00106 oss.str(std::string()); 00107 success=(mpiErr==0); 00108 #endif 00109 } else { 00110 ofs << oss.str(); 00111 oss.str(std::string()); 00112 success=!ofs.fail(); 00113 } 00114 return success; 00115 } 00116 00117 bool writeShared(std::ostringstream& oss) 00118 { 00119 bool success=false; 00120 if (mpiSize>1) { 00121 #ifdef ESYS_MPI 00122 MPI_Status mpiStatus; 00123 std::string contents = oss.str(); 00124 int mpiErr = MPI_File_write_shared( 00125 fileHandle, const_cast<char*>(contents.c_str()), 00126 contents.length(), MPI_CHAR, &mpiStatus); 00127 oss.str(std::string()); 00128 success=(mpiErr==0); 00129 #endif 00130 } else { 00131 ofs << oss.str(); 00132 oss.str(std::string()); 00133 success=!ofs.fail(); 00134 } 00135 return success; 00136 } 00137 00138 bool writeAt(std::ostringstream& oss, long offset) 00139 { 00140 bool success=false; 00141 if (mpiSize>1) { 00142 #ifdef ESYS_MPI 00143 MPI_Status mpiStatus; 00144 std::string contents = oss.str(); 00145 int mpiErr = MPI_File_write_at( 00146 fileHandle, offset, const_cast<char*>(contents.c_str()), 00147 contents.length(), MPI_CHAR, &mpiStatus); 00148 oss.str(std::string()); 00149 success=(mpiErr==0); 00150 #endif 00151 } else { 00152 ofs.seekp(offset); 00153 ofs << oss.str(); 00154 oss.str(std::string()); 00155 success=!ofs.fail(); 00156 } 00157 return success; 00158 } 00159 00160 void close() 00161 { 00162 if (mpiSize>1) { 00163 #ifdef ESYS_MPI 00164 MPI_File_close(&fileHandle); 00165 #endif 00166 } else { 00167 ofs.close(); 00168 } 00169 } 00170 00171 private: 00172 int mpiRank, mpiSize; 00173 #ifdef ESYS_MPI 00174 MPI_Comm mpiComm; 00175 MPI_File fileHandle; 00176 #else 00177 void* mpiComm; 00178 #endif 00179 std::ofstream ofs; 00180 }; 00181 00182 00183 } // namespace esysUtils 00184 00185 #endif // __ESYS_FILEWRITER_H__ 00186