degate  0.1.2
XmlRpc.cc
Go to the documentation of this file.
00001 /* -*-c++-*-
00002 
00003   This file is part of the IC reverse engineering tool degate.
00004 
00005   Copyright 2008, 2009, 2010 by Martin Schobert
00006 
00007   Degate is free software: you can redistribute it and/or modify
00008   it under the terms of the GNU General Public License as published by
00009   the Free Software Foundation, either version 3 of the License, or
00010   any later version.
00011 
00012   Degate is distributed in the hope that it will be useful,
00013   but WITHOUT ANY WARRANTY; without even the implied warranty of
00014   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015   GNU General Public License for more details.
00016 
00017   You should have received a copy of the GNU General Public License
00018   along with degate. If not, see <http://www.gnu.org/licenses/>.
00019 
00020 */
00021 
00022 #include <XmlRpc.h>
00023 #include <Wire.h>
00024 #include <Via.h>
00025 
00026 #include <boost/foreach.hpp>
00027 
00028 using namespace degate;
00029 using namespace std;
00030 
00031 
00032 xmlrpc_c::value degate::remote_method_call(std::string const& server_url,
00033                                            std::string const& method_name,
00034                                            xmlrpc_c::paramList const& params) {
00035 
00036   xmlrpc_c::clientXmlTransport_curl myTransport;
00037   xmlrpc_c::client_xml myClient(&myTransport);
00038 
00039   xmlrpc_c::rpcPtr myRpcP(method_name, params);
00040   xmlrpc_c::carriageParm_curl0 myCarriageParam(server_url);
00041 
00042   myRpcP->call(&myClient, &myCarriageParam);
00043 
00044   assert(myRpcP->isFinished());
00045 
00046   return myRpcP->getResult();
00047 }
00048 
00049 
00050 void degate::push_changes_to_server(std::string const& server_url, LogicModel_shptr lmodel) {
00051 
00052   // iterate over gates
00053   for(LogicModel::object_collection::iterator iter = lmodel->objects_begin();
00054       iter != lmodel->objects_end(); ++iter) {
00055 
00056     object_id_t local_oid = iter->second->get_object_id();
00057 
00058     if(RemoteObject_shptr ro = std::dynamic_pointer_cast<RemoteObject>((*iter).second)) {
00059 
00060       if(!ro->has_remote_object_id()) {
00061         std::cout << "Push object to server." << std::endl;
00062         object_id_t remote_oid = ro->push(server_url);
00063 
00064         lmodel->update_roid_mapping(remote_oid, local_oid);
00065       }
00066     }
00067   }
00068 
00069   BOOST_FOREACH(object_id_t id, lmodel->get_removed_remote_objetcs_list()) {
00070     xmlrpc_c::paramList params;
00071     params.add(xmlrpc_c::value_string("remove"));
00072     params.add(xmlrpc_c::value_int(id));
00073 
00074     remote_method_call(server_url, "degate.push", params);
00075 
00076     debug(TM, "Send remove message for object with remote ID %d", id);
00077   }
00078 
00079   lmodel->reset_removed_remote_objetcs_list();
00080 }
00081 
00082 
00083 void degate::process_changelog_command(LogicModel_shptr lmodel,
00084                                        transaction_id_t transaction_id,
00085                                        std::vector<xmlrpc_c::value> const& command) {
00086 
00087   debug(TM, "XMLRPC: process received command for transaction %d", transaction_id);
00088 
00089   if(lmodel->get_local_oid_for_roid(transaction_id) != 0) {
00090     debug(TM, "XMLRPC: transaction %d aready known.", transaction_id);
00091     return;
00092   }
00093 
00094 
00095   if(command.size() < 2) throw XMLRPCException("Command has not enough parameters.");
00096 
00097   if(command[0].type() != xmlrpc_c::value::TYPE_STRING)
00098     throw XMLRPCException("Command parameter is not a string");
00099 
00100   const std::string command_str = xmlrpc_c::value_string(command[0]);
00101   std::cout << " cmd: " << command_str << std::endl;
00102 
00103   if(!command_str.compare("remove")) {
00104     if(command.size() < 2)
00105       throw XMLRPCException("Command wire add has less then 8 parameters.");
00106     int ro_id = xmlrpc_c::value_int(command[1]);
00107     lmodel->remove_remote_object(ro_id);
00108   }
00109 
00110   else if( !command_str.compare("add")) {
00111 
00112     const std::string obj_type_str = xmlrpc_c::value_string(command[1]);
00113 
00114     if(!obj_type_str.compare("wire")) {
00115       if(command.size() < 8)
00116         throw XMLRPCException("Command wire add has less then 8 parameters.");
00117 
00118       int layer_id = xmlrpc_c::value_int(command[2]);
00119       int from_x = xmlrpc_c::value_int(command[3]);
00120       int from_y = xmlrpc_c::value_int(command[4]);
00121       int to_x = xmlrpc_c::value_int(command[5]);
00122       int to_y = xmlrpc_c::value_int(command[6]);
00123       unsigned int diameter = xmlrpc_c::value_int(command[7]);
00124 
00125       Wire_shptr w(new Wire(from_x, from_y, to_x, to_y, diameter));
00126       w->set_remote_object_id(transaction_id);
00127       Layer_shptr layer = lmodel->get_layer_by_id(layer_id);
00128       lmodel->add_object(layer, w);
00129     }
00130     else if(!obj_type_str.compare("via")) {
00131       if(command.size() < 7)
00132         throw XMLRPCException("Command via add has less then 8 parameters.");
00133 
00134       int layer_id = xmlrpc_c::value_int(command[2]);
00135       int x = xmlrpc_c::value_int(command[3]);
00136       int y = xmlrpc_c::value_int(command[4]);
00137       unsigned int diameter = xmlrpc_c::value_int(command[5]);
00138       const std::string direction = xmlrpc_c::value_string(command[6]);
00139 
00140       Via_shptr v(new Via(x, y, diameter, Via::get_via_direction_from_string(direction)));
00141       v->set_remote_object_id(transaction_id);
00142       Layer_shptr layer = lmodel->get_layer_by_id(layer_id);
00143       lmodel->add_object(layer, v);
00144     }
00145   }
00146 
00147   /*
00148   for(std::vector<xmlrpc_c::value>::const_iterator iter = command.begin();
00149       iter != command.end(); ++iter)
00150     std::cout << "\ttype " << (*iter).type() << std::endl;
00151   }
00152   */
00153 
00154 }
00155 
00156 transaction_id_t degate::pull_changes_from_server(std::string const& server_url,
00157                                                   LogicModel_shptr lmodel,
00158                                                   transaction_id_t start_tid) {
00159   try {
00160     xmlrpc_c::paramList params;
00161     params.add(xmlrpc_c::value_int(start_tid));
00162     xmlrpc_c::value_array ret(remote_method_call(server_url, "degate.pull", params));
00163 
00164     std::vector<xmlrpc_c::value> v(ret.vectorValueValue());
00165 
00166     if(start_tid == 0) ++start_tid;
00167 
00168     debug(TM, "Received %d changes since transaction %ld", v.size(), start_tid);
00169 
00170     unsigned int pos = 0;
00171     for(std::vector<xmlrpc_c::value>::const_iterator iter = v.begin();
00172         iter != v.end(); ++iter, pos++) {
00173       xmlrpc_c::value_array const& command(*iter);
00174       process_changelog_command(lmodel, start_tid + pos, command.vectorValueValue());
00175 
00176       /* If the process_changelog_command() fails with an exception, changes
00177          were already made to the logic model. That is no problem, because
00178          process_changelog_command() checks this case.
00179       */
00180     }
00181 
00182     return start_tid + v.size();
00183   }
00184   catch(XMLRPCException const& e) {
00185     throw;
00186   }
00187   catch(exception const& e) {
00188     cerr << "Client threw error: " << e.what() << endl;
00189     throw XMLRPCException(e.what());
00190   }
00191   catch(...) {
00192     cerr << "Client threw unexpected error." << endl;
00193     throw XMLRPCException("Client threw unexpected error.");
00194   }
00195 
00196   return start_tid;
00197 }
00198