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