ArchiveOpener.cpp
00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037 #include <boost/archive/text_oarchive.hpp>
00038 #include <boost/archive/text_iarchive.hpp>
00039
00040 #include <sstream>
00041 #include <iostream>
00042
00043 #include "ArchiveOpener.hpp"
00044 #include "ArchiveLocationInfo.hpp"
00045 #include "ProcessSpecificArchive.hpp"
00046 #include "Exception.hpp"
00047 #include "OutputFileHandler.hpp"
00048
00055 template<>
00056 ArchiveOpener<boost::archive::text_iarchive, std::ifstream>::ArchiveOpener(
00057 const FileFinder& rDirectory,
00058 const std::string& rFileNameBase,
00059 unsigned procId)
00060 : mpCommonStream(NULL),
00061 mpPrivateStream(NULL),
00062 mpCommonArchive(NULL),
00063 mpPrivateArchive(NULL)
00064 {
00065
00066 ArchiveLocationInfo::SetArchiveDirectory(rDirectory);
00067 std::string private_path = ArchiveLocationInfo::GetProcessUniqueFilePath(rFileNameBase, procId);
00068 std::stringstream common_path;
00069 common_path << ArchiveLocationInfo::GetArchiveDirectory() << rFileNameBase;
00070
00071
00072 mpCommonStream = new std::ifstream(common_path.str().c_str(), std::ios::binary);
00073 if (!mpCommonStream->is_open())
00074 {
00075 delete mpCommonStream;
00076 EXCEPTION("Cannot load main archive file: " + common_path.str());
00077 }
00078
00079 try
00080 {
00081 mpCommonArchive = new boost::archive::text_iarchive(*mpCommonStream);
00082 }
00083 catch (boost::archive::archive_exception& boost_exception)
00084 {
00085 if (boost_exception.code == boost::archive::archive_exception::unsupported_version)
00086 {
00087
00088 delete mpCommonArchive;
00089 delete mpCommonStream;
00090 EXCEPTION("Could not open Boost archive '" + common_path.str() + "' because it was written by a more recent Boost. Check process-specific archives too");
00091 }
00092 else
00093 {
00094
00095 #define COVERAGE_IGNORE
00096 throw boost_exception;
00097 #undef COVERAGE_IGNORE
00098 }
00099 }
00100
00101
00102 mpPrivateStream = new std::ifstream(private_path.c_str(), std::ios::binary);
00103 if (!mpPrivateStream->is_open())
00104 {
00105 delete mpPrivateStream;
00106 delete mpCommonArchive;
00107 delete mpCommonStream;
00108 EXCEPTION("Cannot load secondary archive file: " + private_path);
00109 }
00110 mpPrivateArchive = new boost::archive::text_iarchive(*mpPrivateStream);
00111 ProcessSpecificArchive<boost::archive::text_iarchive>::Set(mpPrivateArchive);
00112 }
00113
00114 template<>
00115 ArchiveOpener<boost::archive::text_iarchive, std::ifstream>::~ArchiveOpener()
00116 {
00117 ProcessSpecificArchive<boost::archive::text_iarchive>::Set(NULL);
00118 delete mpPrivateArchive;
00119 delete mpPrivateStream;
00120 delete mpCommonArchive;
00121 delete mpCommonStream;
00122 }
00123
00130 template<>
00131 ArchiveOpener<boost::archive::text_oarchive, std::ofstream>::ArchiveOpener(
00132 const FileFinder& rDirectory,
00133 const std::string& rFileNameBase,
00134 unsigned procId)
00135 : mpCommonStream(NULL),
00136 mpPrivateStream(NULL),
00137 mpCommonArchive(NULL),
00138 mpPrivateArchive(NULL)
00139 {
00140
00141 if (procId != PetscTools::GetMyRank())
00142 {
00143 EXCEPTION("Specifying the secondary archive file ID doesn't make sense when writing.");
00144 }
00145
00146
00147 ArchiveLocationInfo::SetArchiveDirectory(rDirectory);
00148 if (ArchiveLocationInfo::GetIsDirRelativeToChasteTestOutput())
00149 {
00150
00151 OutputFileHandler handler(ArchiveLocationInfo::GetArchiveRelativePath(), false);
00152 }
00153 std::string private_path = ArchiveLocationInfo::GetProcessUniqueFilePath(rFileNameBase);
00154 std::stringstream common_path;
00155 common_path << ArchiveLocationInfo::GetArchiveDirectory() << rFileNameBase;
00156
00157
00158 if (PetscTools::AmMaster())
00159 {
00160 mpCommonStream = new std::ofstream(common_path.str().c_str(), std::ios::binary | std::ios::trunc);
00161 if (!mpCommonStream->is_open())
00162 {
00163 delete mpCommonStream;
00164 EXCEPTION("Failed to open main archive file for writing: " + common_path.str());
00165 }
00166 }
00167 else
00168 {
00169
00170 #ifdef _MSC_VER
00171 mpCommonStream = new std::ofstream("NUL", std::ios::binary | std::ios::trunc);
00172 #else
00173 mpCommonStream = new std::ofstream("/dev/null", std::ios::binary | std::ios::trunc);
00174 #endif
00175 #define COVERAGE_IGNORE
00176 if (!mpCommonStream->is_open())
00177 {
00178 delete mpCommonStream;
00179 EXCEPTION("Failed to open dummy archive file '/dev/null' for writing");
00180 }
00181 #undef COVERAGE_IGNORE
00182 }
00183 mpCommonArchive = new boost::archive::text_oarchive(*mpCommonStream);
00184
00185
00186 mpPrivateStream = new std::ofstream(private_path.c_str(), std::ios::binary | std::ios::trunc);
00187 if (!mpPrivateStream->is_open())
00188 {
00189 delete mpPrivateStream;
00190 delete mpCommonArchive;
00191 delete mpCommonStream;
00192 EXCEPTION("Failed to open secondary archive file for writing: " + private_path);
00193 }
00194 mpPrivateArchive = new boost::archive::text_oarchive(*mpPrivateStream);
00195 ProcessSpecificArchive<boost::archive::text_oarchive>::Set(mpPrivateArchive);
00196 }
00197
00198 template<>
00199 ArchiveOpener<boost::archive::text_oarchive, std::ofstream>::~ArchiveOpener()
00200 {
00201 ProcessSpecificArchive<boost::archive::text_oarchive>::Set(NULL);
00202 delete mpPrivateArchive;
00203 delete mpPrivateStream;
00204 delete mpCommonArchive;
00205 delete mpCommonStream;
00206
00207
00208
00209
00210
00211
00212 PetscTools::Barrier("~ArchiveOpener");
00213 }