SAGA Adaptor CPI v.1.0
serialization.cpp
Go to the documentation of this file.
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 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines