escript  Revision_
esysFileWriter.h
Go to the documentation of this file.
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