|
orca-robotics INTRODUCTION Overview Download and Install Quick Start Documentation Publications REPOSITORY Interfaces Components Libraries Utilities Software Map DEVELOPER Tutorials Examples Dev Guide Dashboard Wiki login/pass: orca/orca PEOPLE Contributors Users Project Download Mailing lists
|
icestormutils.h00001 00002 00003 /* 00004 * Orca-Robotics Project: Components for robotics 00005 * http://orca-robotics.sf.net/ 00006 * Copyright (c) 2004-2008 Alex Brooks, Alexei Makarenko, Tobias Kaupp 00007 * 00008 * This copy of Orca is licensed to you under the terms described in 00009 * the LICENSE file included in this distribution. 00010 * 00011 */ 00012 00013 #ifndef ORCAICE_ICESTORM_UTILITIES_H 00014 #define ORCAICE_ICESTORM_UTILITIES_H 00015 00016 #include <Ice/Ice.h> 00017 #include <IceStorm/IceStorm.h> 00018 00019 #include <orcaice/context.h> 00020 #include <orcaice/exceptions.h> 00021 #include <orcaice/configutils.h> 00022 #include <orcaice/printutils.h> 00023 #include <orcaice/stringutils.h> 00024 00025 namespace orcaice 00026 { 00031 00052 template<class ConsumerProxyType> 00053 ConsumerProxyType 00054 createConsumerInterface( const Context & context, 00055 Ice::ObjectPtr & consumer ) 00056 { 00057 // create servant and tell adapter about it (let it make up a globally unique name) 00058 // NOTE: addWithUUID() does not throw exceptions. 00059 try 00060 { 00061 Ice::ObjectPrx obj = context.adapter()->addWithUUID( consumer ); 00062 00063 // make a direct proxy 00064 Ice::ObjectPrx prx = context.adapter()->createDirectProxy( obj->ice_getIdentity() ); 00065 return ConsumerProxyType::uncheckedCast( prx ); 00066 } 00067 catch( const Ice::ObjectAdapterDeactivatedException &e ) 00068 { 00069 std::stringstream ss; 00070 ss << "orcaice::Component: Failed to create consumer interface because the adapter is destroyed : " << e; 00071 bool localOnly = true; 00072 context.tracer().warning( ss.str(), 1, localOnly ); 00073 throw orcaice::ComponentDeactivatingException( ERROR_INFO, ss.str() ); 00074 } 00075 } 00076 00077 // FUNCTIONS WITHOUT DOXYGEN TAGS ARE UTILITY FUNCTIONS 00078 // THEY ARE PUBLICLY AVAILABLE BUT ARE NOT ADVERTIZED THROUGH DOXYGEN 00079 00080 /* 00081 * Behaves the same as the one above but connects to the topic manager 00082 * specified in the current properties. 00083 */ 00084 IceStorm::TopicPrx connectToIceStormTopicPrx( const Context &, 00085 const std::string & topicName, 00086 bool createIfMissing=false ); 00087 00088 /* 00089 * Behaves the same as the one above but connects to the topic manager 00090 * specified in the communicator's properties. 00091 */ 00092 IceStorm::TopicPrx connectToIceStormTopicPrx( const Ice::CommunicatorPtr & communicator, 00093 const std::string & topicName, 00094 bool createIfMissing=false ); 00095 00096 /* 00097 * Given the stingified proxy to topic manager and topic name, connect to the topic proxy. 00098 * If topic manager does not exist, throws Exception exception. 00099 */ 00100 IceStorm::TopicPrx connectToIceStormTopicPrxWithManager( const Ice::CommunicatorPtr & communicator, 00101 const std::string & topicName, 00102 const std::string & topicManagerString, 00103 bool createIfMissing=false ); 00104 00105 /* 00106 * Publisher is used from the provider end. It is the consumer of information. 00107 * So you can push data into it. 00108 */ 00109 Ice::ObjectPrx connectToIceStormTopicPublisherPrx( const Ice::CommunicatorPtr & communicator, 00110 const std::string & topicName ); 00111 00112 /* 00113 * Behaves like the one above. 00114 */ 00115 Ice::ObjectPrx connectToIceStormTopicPublisherPrx( const IceStorm::TopicPrx & topic ); 00116 00117 00126 template<class ConsumerProxyType> 00127 IceStorm::TopicPrx 00128 connectToTopicWithTag( const Context & context, 00129 ConsumerProxyType & publisher, 00130 const std::string & interfaceTag, 00131 const std::string & subtopic="*" ) 00132 { 00133 context.tracer().debug( "orcaice::connectToTopicWithTag() tag="+interfaceTag, 10 ); 00134 00135 // lookup the name of the interface in the config file and generate topic name. 00136 // this generates a standard topic name based on fully-qualified interface name. 00137 std::string topicName = orcaice::toString( 00138 orcaice::getProvidedTopicWithTag( context, interfaceTag, subtopic ) ); 00139 00140 // do the conversion to string by hand, to cut dependency on libOrcaObj 00141 // see <orcaobj/stringutils.cpp> 00142 // orca::FQTopicName name = orcaice::getProvidedTopicWithTag( context, interfaceTag, subtopic ); 00143 // std::string topicName = name.iface + "/" + name.topic + "@" + name.platform + "/" + name.component; 00144 00145 return connectToTopicWithString( context, publisher, topicName ); 00146 } 00147 00159 template<class ConsumerProxyType> 00160 IceStorm::TopicPrx 00161 connectToTopicWithString( const Context & context, 00162 ConsumerProxyType & publisher, 00163 const std::string & topicName ) 00164 { 00165 IceStorm::TopicPrx topicPrx; 00166 00167 try { 00168 const bool createIfMissing = true; 00169 // 00170 // set the proxy to the topic 00171 // 00172 topicPrx = connectToIceStormTopicPrx( context.communicator(), topicName, createIfMissing ); 00173 00174 Ice::ObjectPrx obj = connectToIceStormTopicPublisherPrx( topicPrx ); 00175 // 00176 // set the proxy to the publisher 00177 // 00178 publisher = ConsumerProxyType::uncheckedCast(obj); 00179 } 00180 //catch ( const gbxutilacfr::Exception & e ) { 00181 // we'll catch it here if the topic manager does not exist 00182 //} 00183 catch ( Ice::ConnectionRefusedException &e ) 00184 { 00185 // Give some feedback as to why this isn't working 00186 std::stringstream ss; ss<<"Error while connecting to IceStorm topic publisher '"<<topicName<<"': "<<e; 00187 bool localOnly = true; 00188 initTracerError( context, ss.str(), 2, localOnly ); 00189 initTracerInfo( context, "hint: Is IceStorm running?", 10, localOnly ); 00190 throw orcaice::NetworkException( ERROR_INFO, ss.str() ); 00191 } 00192 catch( const Ice::LocalException &e ) 00193 { 00194 std::stringstream ss; 00195 ss<<"Error while connecting to IceStorm topic publisher '"<<topicName<<"': "<<e; 00196 bool localOnly = true; 00197 initTracerError( context, ss.str(), 2, localOnly ); 00198 throw gbxutilacfr::Exception( ERROR_INFO, ss.str() ); 00199 } 00200 catch ( Ice::Exception &e ) 00201 { 00202 // Give some feedback as to why this isn't working 00203 std::stringstream ss; ss<<"Error while connecting to IceStorm topic publisher '"<<topicName<<"': "<<e; 00204 bool localOnly = true; 00205 initTracerError( context, ss.str(), 2, localOnly ); 00206 throw orcaice::NetworkException( ERROR_INFO, ss.str() ); 00207 } 00208 00209 return topicPrx; 00210 } 00211 00213 00214 namespace detail { 00215 00216 // Catches all exceptions. 00217 // Returns: 00218 // 0 : if re-connected 00219 // 1 : if failed to re-connect 00220 // -1 : if got CommunicatorDestroyedException 00221 template<class ConsumerPrxType> 00222 int 00223 tryReconnectToIceStorm( orcaice::Context &context, 00224 ConsumerPrxType &publisherPrx, 00225 IceStorm::TopicPrx &topicPrx, 00226 const std::string &topicName ) 00227 { 00228 try { 00229 topicPrx = orcaice::connectToTopicWithString<ConsumerPrxType> 00230 ( context, publisherPrx, topicName ); 00231 00232 std::string msg = "Re-connected to IceStorm topic "+topicName; 00233 context.tracer().info( msg ); 00234 00235 return 0; 00236 } 00237 catch ( const Ice::CommunicatorDestroyedException& ) 00238 { 00239 return -1; 00240 } 00241 catch ( ... ) 00242 { 00243 std::string msg = "Re-connection to IceStorm topic "+topicName+" failed."; 00244 bool localOnly = true; 00245 context.tracer().info( msg, 1, localOnly ); 00246 return 1; 00247 } 00248 } 00249 00250 } 00251 00253 00254 00264 template<class ConsumerPrxType, class DataType> 00265 void tryPushToIceStormWithReconnect( orcaice::Context &context, 00266 ConsumerPrxType &publisherPrx, 00267 const DataType &data, 00268 IceStorm::TopicPrx &topicPrx, 00269 const std::string &topicName ) 00270 { 00271 // check that communicator still exists 00272 if ( !context.communicator() ) { 00273 return; 00274 } 00275 00276 // check that we are connected to the publisher 00277 if ( !publisherPrx ) { 00278 int reconnected = detail::tryReconnectToIceStorm( 00279 context, publisherPrx, topicPrx, topicName ); 00280 bool localOnly = true; 00281 if ( reconnected==0 ) { 00282 context.tracer().info( "(while pushing data to IceStorm) connected to publisher.", 1, localOnly ); 00283 } 00284 else if ( reconnected>0 ) { 00285 context.tracer().info( "(while pushing data to IceStorm) failed to connect to publisher.", 1, localOnly ); 00286 return; 00287 } 00288 else { 00289 // CommunicatorDestroyedException 00290 // If we see this, we're obviously shutting down. Don't bitch about anything. 00291 return; 00292 } 00293 } 00294 00295 try { 00296 publisherPrx->setData( data ); 00297 } 00298 catch ( Ice::CommunicatorDestroyedException & ) 00299 { 00300 // If we see this, we're obviously shutting down. Don't bitch about anything. 00301 } 00302 catch ( Ice::Exception &e ) 00303 { 00304 // This could happen if IceStorm dies. 00305 // If we're running in an IceBox and the IceBox is shutting down, 00306 // this is expected (our co-located IceStorm is obviously going down). 00307 std::stringstream ss; 00308 ss << "(while pushing data to topic "<<topicName<<") 1st attempt failed: " << e.what(); 00309 bool localOnly = true; 00310 context.tracer().warning( ss.str(), 1, localOnly ); 00311 00312 // If IceStorm just re-started for some reason though, we want to try to re-connect 00313 int reconnected = detail::tryReconnectToIceStorm( 00314 context, publisherPrx, topicPrx, topicName ); 00315 if ( reconnected==0 ) 00316 { 00317 try { 00318 // try again to push that last bit of info 00319 publisherPrx->setData( data ); 00320 } 00321 catch ( Ice::Exception &e ) 00322 { 00323 std::stringstream ss; 00324 ss << "(while pushing data to topic "<<topicName<<") 2nd attempt failed: " << e.what(); 00325 bool localOnly = true; 00326 context.tracer().warning( ss.str(), 1, localOnly ); 00327 } 00328 } 00329 } 00330 } 00331 00333 00334 } // namespace 00335 00336 #endif |
Webmaster: Tobias Kaupp (tobasco at users.sourceforge.net)
1.4.5