SAGA Adaptor CPI v.1.0
|
00001 // Copyright (c) 2005-2009 Hartmut Kaiser 00002 // 00003 // Distributed under the Boost Software License, Version 1.0. (See accompanying 00004 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 00005 00006 #include <boost/plugin/dll.hpp> 00007 #include <boost/archive/text_iarchive.hpp> 00008 #include <boost/archive/text_oarchive.hpp> 00009 #include <boost/serialization/serialization.hpp> 00010 #include <boost/serialization/shared_ptr.hpp> 00011 00012 #include <saga/saga/util.hpp> 00013 #include <saga/impl/runtime.hpp> 00014 #include <saga/saga/version.hpp> 00015 00016 #include <saga/impl/engine/context_base.hpp> 00017 #include <saga/impl/context_serialization.hpp> 00018 #include <saga/impl/engine/session.hpp> 00019 #include <saga/saga/adaptors/serialization.hpp> 00020 00022 namespace saga { namespace adaptors 00023 { 00024 00025 // retrieve the name of the package containing for the implementation of the 00026 // given SAGA object type 00027 inline std::string 00028 get_package_name(saga::object obj, saga::object::type type) 00029 { 00030 // The sequence of package names in this array should be equivalent to the 00031 // definition sequence of the corresponding saga object types 00032 // (see saga/object.hpp) 00033 struct modulename 00034 { 00035 char const* const package_name; 00036 bool is_package; 00037 }; 00038 00039 static modulename package_names[] = 00040 { 00041 { "core", false }, // Exception = 1, 00042 { "core", false }, // URL = 2, 00043 { "core", false }, // Buffer = 3, 00044 { "core", false }, // Session = 4, 00045 { "core", false }, // Context = 5, 00046 { "core", false }, // Task = 6, 00047 { "core", false }, // TaskContainer = 7, 00048 { "core", false }, // Metric = 8, 00049 { "namespace", true }, // NSEntry = 9, 00050 { "namespace", true }, // NSDirectory = 10, 00051 { "filesystem", true }, // IOVec = 11, 00052 { "filesystem", true }, // File = 12, 00053 { "filesystem", true }, // Directory = 13, 00054 { "replica", true }, // LogicalFile = 14, 00055 { "replica", true }, // LogicalDirectory = 15, 00056 { "job", true }, // JobDescription = 16, 00057 { "job", true }, // JobService = 17, 00058 { "job", true }, // Job = 18, 00059 { "job", true }, // JobSelf = 19, 00060 { "stream", true }, // StreamServer = 20, 00061 { "stream", true }, // Stream = 21, 00062 { "rpc", true }, // Parameter = 22, 00063 { "rpc", true }, // RPC = 23, 00064 00065 // SAGA Message API extension 00066 { "message", true }, // Msg = 24, 00067 { "message", true }, // Endpoint = 25, 00068 00069 // SAGA Information services extension 00070 { "advert", true }, // Advert = 26, 00071 { "advert", true }, // AdvertDirectory = 27, 00072 00073 // SAGA Service Discovery extension 00074 { "sd", true }, // ServiceDescription = 28, 00075 { "sd", true }, // ServiceDiscoverer = 29, 00076 { "sd", true }, // ServiceData = 30, 00077 00078 // SAGA Checkpoint and Recovery extension 00079 { "cpr", true }, // CPRJobDescription = 31, 00080 { "cpr", true }, // CPRJobService = 32, 00081 { "cpr", true }, // CPRJob = 33, 00082 { "cpr", true }, // CPRJobSelf = 34, 00083 { "cpr", true }, // CPRCheckpoint = 35, 00084 { "cpr", true }, // CPRDirectory = 36, 00085 00086 // SAGA Information System Navigator extension 00087 { "isn", true }, // EntityData = 37, 00088 { "isn", true }, // EntityDataSet = 38, 00089 { "isn", true }, // EntityNavigator = 39 00090 }; 00091 00092 if (type < saga::object::Exception || type > saga::object::ServiceData) 00093 { 00094 SAGA_THROW_VERBATIM(obj, "Attempt to retrieve package name from " 00095 "unknown SAGA object type.", saga::BadParameter); 00096 } 00097 00098 std::string package(package_names[type-1].package_name); 00099 return package_names[type-1].is_package ? 00100 SAGA_MANGLE_PACKAGE_NAME_STR(package) : 00101 SAGA_MANGLE_ENGINE_NAME_STR(package); 00102 } 00103 00104 // serialize a saga::object into a string representation 00105 std::string serialize(saga::object obj) 00106 { 00107 using namespace boost::serialization; 00108 using namespace boost::archive; 00109 00110 SAGA_OSSTREAM strm; 00111 try { 00112 text_oarchive oa(strm); 00113 00114 // save the version of the SAGA engine 00115 unsigned int version = SAGA_VERSION_FULL; 00116 oa << make_nvp("saga_version", version); 00117 00118 // save the object type 00119 saga::object::type type = obj.get_type(); 00120 oa << make_nvp("type", type); 00121 00122 saga::uuid objid (obj.get_id()); 00123 const std::string str(objid.string()); 00124 oa << make_nvp("id", str); 00125 00126 // save the object implementation 00127 TR1::shared_ptr<saga::impl::object> impl( 00128 saga::impl::runtime::get_impl_object_sp(obj)); 00129 00130 // load the corresponding package and delegate the serialization 00131 std::string package (get_package_name (obj, type)); 00132 package += SAGA_SHARED_LIB_EXTENSION; 00133 00134 boost::plugin::dll d (package); 00135 boost::plugin::plugin_factory <saga::adaptors::serialization> pf (d); 00136 00137 TR1::shared_ptr <saga::adaptors::serialization> ser (pf.create ("serialization")); 00138 00139 // serialize the object 00140 std::string data (ser->serialize(impl)); 00141 00142 oa << make_nvp ("object", data); 00143 } 00144 catch (archive_exception const& e) { 00145 SAGA_THROW_VERBATIM(obj, 00146 std::string("Serialization failed (archive exception): ") + 00147 e.what(), saga::NoSuccess); 00148 } 00149 catch (std::logic_error const& e) { 00150 SAGA_THROW_VERBATIM(obj, std::string("Serialization failed: ") + 00151 e.what(), saga::NoSuccess); 00152 } 00153 return SAGA_OSSTREAM_GETSTRING(strm); 00154 } 00155 00156 // create a saga::object from a given string representation 00157 saga::object deserialize(std::string const& data) 00158 { 00159 return deserialize(saga::detail::get_the_session(), data); 00160 } 00161 00162 saga::object deserialize(saga::session s, std::string const& data) 00163 { 00164 using namespace boost::serialization; 00165 using namespace boost::archive; 00166 00167 TR1::shared_ptr<saga::impl::object> impl; 00168 std::string objid; 00169 00170 try { 00171 SAGA_ISSTREAM strm(data); 00172 text_iarchive ia(strm); 00173 00174 // retrieve the version of the SAGA engine and make sure it is compatible 00175 // with our current version 00176 unsigned int version = 0; 00177 ia >> make_nvp("saga_version", version); // load version 00178 if (!SAGA_VERSION_ISCOMPATIBLE_EX(version)) 00179 { 00180 SAGA_THROW_VERBATIM(s, "Deserialization failed: " 00181 "incompatible version of SAGA modules.", saga::NoSuccess); 00182 } 00183 00184 // retrieve the object type of the stored object 00185 saga::object::type type; 00186 ia >> make_nvp("type", type); 00187 ia >> make_nvp("id", objid); 00188 00189 // load the package corresponding to the object type 00190 std::string package (get_package_name (s, type)); 00191 package += SAGA_SHARED_LIB_EXTENSION; 00192 00193 boost::plugin::dll d(package); 00194 boost::plugin::plugin_factory <saga::adaptors::serialization> pf (d); 00195 TR1::shared_ptr <saga::adaptors::serialization> ser (pf.create("serialization")); 00196 00197 // deserialize the given string 00198 std::string data; 00199 ia >> make_nvp("object", data); 00200 impl = ser->deserialize(s, type, data); 00201 } 00202 catch (archive_exception const& e) { 00203 SAGA_THROW_VERBATIM(s, 00204 std::string("Deserialization failed (archive exception): ") + 00205 e.what(), saga::NoSuccess); 00206 } 00207 catch (std::logic_error const& e) { 00208 SAGA_THROW_VERBATIM(s, std::string("Deserialization failed: ") + 00209 e.what(), saga::NoSuccess); 00210 } 00211 00212 // set the objid 00213 impl->set_uuid(saga::uuid(objid.c_str())); 00214 return saga::impl::runtime::get_object(impl); 00215 } 00216 00218 }} // namespace saga::adaptors 00219 00221 namespace saga { namespace impl 00222 { 00223 // serialization support for the engine 00224 engine_serialization::~engine_serialization() 00225 { 00226 } 00227 00228 std::string engine_serialization::serialize(TR1::shared_ptr<saga::impl::object> obj) 00229 { 00230 // get the type of the object (has been serialized already) 00231 saga::object::type type = obj->get_type(); 00232 if (saga::object::Session != type && saga::object::Context != type) 00233 { 00234 SAGA_THROW_VERBATIM(obj.get(), "engine_serialization::serialize: " 00235 "Unknown object type", saga::BadParameter); 00236 } 00237 00238 SAGA_OSSTREAM strm; 00239 { 00240 using namespace boost::serialization; 00241 using namespace boost::archive; 00242 00243 // save package version 00244 text_oarchive oa(strm); 00245 unsigned int version = SAGA_VERSION_FULL; 00246 oa << make_nvp("version", version); 00247 00248 if (saga::object::Session == type) { 00249 // serialize the session data 00250 TR1::shared_ptr<saga::impl::session> s( 00251 TR1::static_pointer_cast<saga::impl::session>(obj)); 00252 saga::impl::session* sp = s.get(); 00253 oa << make_nvp("session", sp); 00254 } 00255 else { 00256 // saga::object::Context == type: serialize the context data 00257 saga::context ctx = saga::impl::runtime::get_object( 00258 TR1::static_pointer_cast<saga::impl::context>(obj)); 00259 oa << make_nvp("context", ctx); 00260 } 00261 } 00262 return SAGA_OSSTREAM_GETSTRING(strm); 00263 } 00264 00265 TR1::shared_ptr<saga::impl::object> engine_serialization::deserialize( 00266 saga::session s, saga::object::type type, std::string const& data) 00267 { 00268 if (saga::object::Session != type && saga::object::Context != type) 00269 { 00270 SAGA_THROW_VERBATIM(s, "engine_serialization::deserialize: " 00271 "Unknown object type", saga::BadParameter); 00272 } 00273 00274 using namespace boost::serialization; 00275 using namespace boost::archive; 00276 00277 SAGA_ISSTREAM strm(data); 00278 text_iarchive ia(strm); 00279 00280 // save package version 00281 unsigned int version = 0; 00282 ia >> make_nvp("version", version); 00283 if (!SAGA_VERSION_ISCOMPATIBLE_EX(version)) 00284 { 00285 SAGA_THROW_VERBATIM(s, "engine_serialization::deserialize: " 00286 "Deserialization failed: incompatible version of SAGA engine " 00287 "module.", saga::NoSuccess); 00288 } 00289 00290 TR1::shared_ptr<saga::impl::object> impl; 00291 if (saga::object::Session == type) { 00292 // deserialize the session data 00293 saga::impl::session* s = 0; 00294 ia >> make_nvp("session", s); 00295 impl.reset(s); 00296 } 00297 else { 00298 // saga::object::Context == type: deserialize the context data 00299 saga::context ctx; 00300 ia >> make_nvp("context", ctx); 00301 impl = saga::impl::runtime::get_impl_sp(ctx); 00302 } 00303 return impl; 00304 } 00305 00307 }} // namespace saga::impl 00308