IceManager.h
Go to the documentation of this file.
1 /*
2  * This file is part of ArmarX.
3  *
4  * Copyright (C) 2011-2016, High Performance Humanoid Technologies (H2T), Karlsruhe Institute of Technology (KIT), all rights reserved.
5  *
6  * ArmarX is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License version 2 as
8  * published by the Free Software Foundation.
9  *
10  * ArmarX is distributed in the hope that it will be useful, but
11  * WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program. If not, see <http://www.gnu.org/licenses/>.
17  *
18  * @package ArmarXCore::core
19  * @author Nils Adermann (naderman at naderman dot de)
20  * @author Jan Issac (jan dot issac at gmx dot de)
21  * @date 2010
22  * @copyright http://www.gnu.org/licenses/gpl-2.0.txt
23  * GNU General Public License
24  */
25 
26 #pragma once
27 
28 #include <stdexcept> // for out_of_range
29 #include <string> // for string, allocator, etc
30 #include <typeinfo> // for type_info
31 #include <utility> // for pair
32 #include <vector> // for vector
33 
34 #include <Ice/Object.h> // for ObjectPtr
35 #include <Ice/Properties.h> // for upCast
36 #include <Ice/Proxy.h> // for ObjectPrx
37 #include <IceUtil/Handle.h> // for Handle, HandleBase
38 #include <IceUtil/Shared.h> // for Shared
39 
40 #include <ArmarXCore/core/logging/Logging.h> // for Logging
41 #include <ArmarXCore/core/system/ImportExport.h> // for ARMARXCORE_IMPORT_EXPORT
43 
44 namespace Ice
45 {
46  class ConnectionRefusedException;
47 
48  class Communicator;
49  typedef ::IceInternal::Handle<::Ice::Communicator> CommunicatorPtr;
50 
51  class ObjectAdapter;
52  typedef ::IceInternal::Handle<::Ice::ObjectAdapter> ObjectAdapterPtr;
53 
54 } // namespace Ice
55 
57 {
58  class Registry;
59 }
60 
61 namespace IceProxy::IceStorm
62 {
63  class TopicManager;
64  class Topic;
65 } // namespace IceProxy::IceStorm
66 
67 namespace IceStorm
68 {
71 } // namespace IceStorm
72 
73 namespace IceGrid
74 {
76 }
77 
78 /**
79  * \namespace armarx
80  * The standard namespace for all classes and components within the ArmarXCore package
81  */
82 namespace armarx
83 {
84  class IceGridAdmin;
86 
87  class IceManager;
88 
89  /**
90  * IceManager smart pointer
91  */
93 
94  /**
95  * Object handles pair which contains the object proxy and its adapter
96  */
97  using ObjectHandles = std::pair<Ice::ObjectPrx, Ice::ObjectAdapterPtr>;
98 
99  /**
100  * @class IceManager
101  * @brief The IceManager class provides simplified access to commonly used Ice features.
102  * @ingroup DistributedProcessingSub
103  * @see Logging
104  */
105  class ARMARXCORE_IMPORT_EXPORT IceManager : public IceUtil::Shared, virtual public Logging
106  {
107  friend class Component;
108 
109  public:
110  /**
111  * Set up an instance of this class with a preexisting communicator.
112  *
113  * This is useful for creating an instance from within an
114  * Ice::Application. If you do not have a communicator yet you can
115  * use one of the static factory methods instead.
116  *
117  * @param communicator An Ice communicator
118  *
119  * @param name A unique name, e.g. the base component's
120  * name. This name is used to create
121  * IceGridObservers, which must have a unique
122  * name.
123  * @param topicSuffix Suffix appended to all topic names.
124  */
125  IceManager(const Ice::CommunicatorPtr& communicator,
126  std::string name = "",
127  const std::string topicSuffix = "");
128 
129  ~IceManager() override;
130 
131  /**
132  * Register an object with Ice for being accessed through IceGrid.
133  *
134  * @param object The object to be registered, implementing an
135  * Ice interface.
136  *
137  * @param objectName The name this object should be available as.
138  *
139  * @return The registered object proxy.
140  */
141  ObjectHandles registerObject(const Ice::ObjectPtr& object,
142  const std::string& objectName,
143  const Ice::ObjectAdapterPtr& adapterToAddTo = nullptr);
144 
145  /**
146  * Removes an object from the IceGrid
147  *
148  * @param objectName The name of the object that should be removed
149  */
150  void removeObject(const std::string& objectName);
151 
152  /**
153  * Retrieves a proxy object.
154  *
155  * @param name Proxy name, e.g. Log
156  * @param endpoints The endpoints, e.g. tcp ‑p 10002
157  *
158  * @return A proxy of the remote instance.
159  */
160  template <class ProxyType>
161  ProxyType
162  getProxy(const std::string& name, const std::string& endpoints = std::string())
163  {
164  std::string proxyString = name;
165 
166  if (!endpoints.empty())
167  {
168  proxyString += std::string(":") + endpoints;
169  }
170 
171  std::string proxyTypedId =
172  proxyString + std::string(":") + std::string(typeid(ProxyType).name());
173 
174  try
175  {
176  return ProxyType::uncheckedCast(implGetCheckedProxy(proxyTypedId));
177  }
178  catch (std::out_of_range& uncheckedProxiesException)
179  {
180  }
181 
182  Ice::ObjectPrx base = communicator_stringToProxy(proxyString);
183 
184  ProxyType proxy;
185 
186  try
187  {
188  proxy = ProxyType::checkedCast(base);
189  implSetCheckedProxy(proxyTypedId, proxy);
190  }
191  catch (const Ice::ConnectionRefusedException&)
192  {
193  std::stringstream exceptionText;
194  exceptionText << "Connection refused for proxy of type '"
195  << GetTypeString<ProxyType>() << "': " << name
196  << " ProxyString: " << proxyString << " Endpoints: " << endpoints
197  << std::endl;
198  throwUserException(exceptionText.str());
199  }
200 
201  if (!proxy)
202  {
203  std::stringstream exceptionText;
204  exceptionText << "Invalid Proxy. Searched for: " << name
205  << " ProxyString: " << proxyString << " Endpoints: " << endpoints
206  << std::endl;
207  throwUserException(exceptionText.str());
208  }
209 
210  return proxy;
211  }
212 
213  void throwUserException(std::string const& message);
214 
215  /**
216  * @brief This functions removes the given proxy from the proxy cache.
217  * This is useful if the cached proxy became invalid.
218  * @param name Proxy name, e.g. Log
219  * @param endpoints The endpoints, e.g. tcp ‑p 10002
220  * @return True, if the proxy was found and removed.
221  */
222  template <class ProxyType>
223  bool
224  removeProxyFromCache(const std::string& name, const std::string& endpoints = std::string())
225  {
226  return removeProxyFromCache(name, typeid(ProxyType).name(), endpoints);
227  }
228 
229  bool removeProxyFromCache(const std::string& name,
230  const std::string& typeName,
231  const std::string& endpoints = std::string());
232 
233  /**
234  * @brief This functions removes the given proxy from the proxy cache.
235  * This is useful if the cached proxy became invalid.
236  * @param name Proxy name, e.g. Log
237  * @param endpoints The endpoints, e.g. tcp ‑p 10002
238  * @return True, if the proxy was found and removed.
239  */
240  bool removeProxyFromCache(const Ice::ObjectPrx& proxy);
241 
242  /**
243  * Provides access to the Ice Storm Topic Manager.
244  * A proxy is created if necessary.
245  *
246  * @return A proxy of the IceStorm TopicManager.
247  */
248  IceStorm::TopicManagerPrx getTopicManager();
249  static IceStorm::TopicManagerPrx GetTopicManager(Ice::CommunicatorPtr communicator);
250 
251  /**
252  * Gets an Ice Storm topic for publishing messages.
253  *
254  * @param topicName The name of the topic to publish on.
255  *
256  * @return A proxy of the topic's remote instance.
257  */
258  template <class TopicProxy>
259  TopicProxy
260  getTopic(const std::string& topicName, bool useUDP = false)
261  {
262  Ice::ObjectPrx pub = __getTopic(topicName, useUDP);
263  TopicProxy castTopic = TopicProxy::uncheckedCast(pub);
264 
265  return castTopic;
266  }
267 
268  /**
269  * Subscribe an object to a particular Ice Storm topic.
270  * If the object is already subscribed to the topic, it will be unsubscribed before.
271  * This is necessary to circumvent the usage from outdated subscriptions due to
272  * unproper exits.
273  *
274  * @param subcriber A proxy of the object to be subscribed,
275  * implementing the interface for listening on this
276  * topic
277  * @param topicName The topic's name
278  * @param orderedPublishing If true, the order of topic calls is ensured. This
279  * might decrease performance.
280  */
281  void subscribeTopic(Ice::ObjectPrx subscriber,
282  const std::string& topicName,
283  bool orderedPublishing = false);
284  void registerAndSubscribeTopic(Ice::ObjectPtr subscriber,
285  const std::string& topicName,
286  bool orderedPublishing = false);
287 
288  /**
289  * Unsubscribe a given subscriber from a given topic
290  *
291  * @param subscriberProxy of the subscriber
292  * @param topicName The name of the subscribed topic.
293  */
294  void unsubscribeTopic(Ice::ObjectPrx subscriberProxy, const std::string& topicName);
295 
296  /**
297  * Registers a specified object that is required before
298  * activating the endpoints.
299  *
300  * @param registrantName Object that has a dependency
301  * @param dependecyObjectName Dependecy object name
302  *
303  *
304  * @throw ObjectAlreadyActiveException
305  */
306  void registerObjectDependency(const std::string& registrantName,
307  const std::string& dependencyObjectName);
308 
309  /**
310  * Registers a delayed topic subscription.
311  *
312  * @param registrantName Registrant object name
313  * @param topicName The topic name that should be subscribed
314  * later on
315  */
316  void registerDelayedTopicSubscription(const std::string& registrantName,
317  const std::string& topicName);
318 
319  /**
320  * Registers a delayed topic retrieval.
321  *
322  * @param registrantName Registrant object name
323  * @param topicName The topic name
324  */
325  void registerDelayedTopicRetrieval(const std::string& registrantName,
326  const std::string& topicName);
327 
328  /**
329  * @brief creates a proxy to the object specified with parameter objectName
330  * and tries to ping it.
331  * @param objectName Name of the object that should be checked
332  * @return true, if reachable
333  */
334  bool isObjectReachable(std::string objectName);
335 
336  /**
337  * @brief creates a proxy to the object specified with parameter objectName
338  * and tries to ping it.
339  * @param objectName Name of the object that should be checked
340  * @return true, if reachable
341  */
342  template <typename ProxyType>
343  bool isObjectReachable(std::string objectName);
344 
345  /**
346  * Short helper method to return the Ice Communicator.
347  *
348  * Uses static communicator() method
349  */
350  const Ice::CommunicatorPtr& getCommunicator();
351 
352  /**
353  * Provides access to the IceGrid Registry. A proxy is created if
354  * necessary.
355  *
356  * @return A proxy of the IceGrid Registy.
357  */
358  IceGrid::RegistryPrx getIceGridRegistry();
359 
360  /**
361  * Provides access to the IceGrid AdminSession via IceGridAdmin.
362  *
363  * @return The IceGrid AdminSession.
364  */
365  const armarx::IceGridAdminPtr& getIceGridSession();
366 
367  /**
368  * Sets the session name
369  */
370  void setName(std::string name);
371 
372  /**
373  * Removes all component objects and topics and shuts down the
374  * communicator.
375  */
376  void shutdown();
377 
378  /**
379  * Waits until all invoked operation has been processed
380  */
381  void waitForShutdown();
382 
383  /**
384  * Determines whether the communicator is shutdown.
385  */
386  bool isShutdown();
387 
388  /**
389  * Destroys the communicator
390  */
391  void destroy();
392 
393  /**
394  * @brief Get the suffix that is appended to all topics.
395  */
396  std::string getTopicSuffix() const;
397 
398  private:
399  Ice::ObjectPrx communicator_stringToProxy(std::string const& proxyString);
400 
401  Ice::ObjectPrx __getTopic(const std::string& topicName, bool useUDP = false);
402 
403  struct ObjectEntry;
404 
405  struct DependencyObjectEntry : public IceUtil::Shared
406  {
407  DependencyObjectEntry(std::string name, Ice::ObjectPrx proxy) :
408  name(name), proxy(proxy), resolved(false)
409  {
410  }
411 
412  std::string name;
413  Ice::ObjectPrx proxy;
414  bool resolved;
415  };
416 
417  using ObjectEntryPtr = IceUtil::Handle<ObjectEntry>;
418  using DependencyObjectEntryPtr = IceUtil::Handle<DependencyObjectEntry>;
419 
420  using TopicList = std::vector<std::string>;
421  using DependencyList = std::vector<DependencyObjectEntryPtr>;
422 
423  /**
424  * Subscribes all topics registered for a delayed subscription
425  */
426  void subscribeTopics(Ice::ObjectPrx subscriber,
427  const TopicList& topics,
428  bool orderedPublishing = false);
429 
430  /**
431  * gets all topics registered for a delayed retrieval
432  */
433  void retrieveTopics(const TopicList& topics);
434 
435  /**
436  * Check the existence of required servants.
437  *
438  * @return True if all servant objects exist, otherise false
439  */
440  void resolveObjectDependencies();
441 
442  /**
443  * Returns the requested object entry if exists, otherwise
444  * a new entry is created and return.
445  *
446  * @param objectName Object name of the entry
447  *
448  * @return Smart pointer of the requested ObjectEntry.
449  */
450  ObjectEntryPtr getOrCreateObjectEntry(const std::string& objectName);
451 
452  /**
453  * Cleans up all current IceStorm connections.
454  */
455  void cleanUp();
456 
457  /**
458  * Retrieves an Ice Storm topic from the topic manager if necessary.
459  * Proxies are cached.
460  *
461  * @param topicName The name of the topic to publish on.
462  *
463  * @return A generic proxy instance of the topic. Has to be cast for
464  * actual messages to be sent.
465  */
466  IceStorm::TopicPrx retrieveTopic(const std::string& topicName);
467 
468  /**
469  * Retrieves an Ice Storm topic from the topic manager if necessary.
470  * Proxies are cached.
471  *
472  * @param topicName The name of the topic to publish on.
473  *
474  * @return A generic proxy instance of the topic. Has to be cast for
475  * actual messages to be sent.
476  *
477  * @deprecated Use IceManager::retrieveTopic() instead
478  */
479  IceStorm::TopicPrx stormTopicRetrieve(const std::string& topicName);
480 
481  Ice::ObjectPrx implGetCheckedProxy(std::string const& proxyTypedId);
482  void implSetCheckedProxy(std::string const& proxyTypedId, Ice::ObjectPrx const& proxy);
483 
484 
485  struct Impl;
486  std::unique_ptr<Impl> impl;
487  };
488 
489  template <typename ProxyType>
490  bool
491  IceManager::isObjectReachable(std::string objectName)
492  {
493  try
494  {
495  ProxyType prx = getProxy<ProxyType>(objectName);
496  prx->ice_timeout(500)->ice_ping();
497  // if ping'able, object is already registered
498  return true;
499  }
500  catch (...)
501  {
502 
503  return false;
504  }
505  }
506 
507 } // namespace armarx
armarx::IceManagerPtr
IceUtil::Handle< IceManager > IceManagerPtr
IceManager smart pointer.
Definition: ArmarXFwd.h:39
armarx::IceManager::getProxy
ProxyType getProxy(const std::string &name, const std::string &endpoints=std::string())
Retrieves a proxy object.
Definition: IceManager.h:162
armarx::DependencyList
std::map< std::string, ManagedIceObjectDependencyPtr > DependencyList
Map of dependency names and dependecies.
Definition: ManagedIceObjectDependency.h:50
IceStorm
Definition: DBTypes.ice:22
armarx::IceManager
The IceManager class provides simplified access to commonly used Ice features.
Definition: IceManager.h:105
GetTypeString.h
IceProxy::IceGrid
Definition: IceManager.h:56
armarx::IceManager::isObjectReachable
bool isObjectReachable(std::string objectName)
creates a proxy to the object specified with parameter objectName and tries to ping it.
Definition: IceManager.cpp:678
message
message(STATUS "Boost-Library-Dir: " "${Boost_LIBRARY_DIRS}") message(STATUS "Boost-LIBRARIES
Definition: CMakeLists.txt:8
armarx::IceManager::removeProxyFromCache
bool removeProxyFromCache(const std::string &name, const std::string &endpoints=std::string())
This functions removes the given proxy from the proxy cache.
Definition: IceManager.h:224
Ice::CommunicatorPtr
::IceInternal::Handle<::Ice::Communicator > CommunicatorPtr
Definition: IceManager.h:48
IceInternal::Handle<::Ice::Communicator >
armarx::IceManager::getTopic
TopicProxy getTopic(const std::string &topicName, bool useUDP=false)
Gets an Ice Storm topic for publishing messages.
Definition: IceManager.h:260
IceProxy::IceStorm
Definition: IceStormInternal.h:444
armarx::ProxyType
ProxyType
Definition: ProxyPropertyDefinition.h:40
armarx::Component
Baseclass for all ArmarX ManagedIceObjects requiring properties.
Definition: Component.h:91
armarx::IceGridAdminPtr
IceUtil::Handle< IceGridAdmin > IceGridAdminPtr
Definition: ArmarXFwd.h:48
Ice
Definition: DBTypes.cpp:63
Ice::ObjectAdapterPtr
::IceInternal::Handle<::Ice::ObjectAdapter > ObjectAdapterPtr
Definition: IceManager.h:51
armarx::Logging
Base Class for all Logging classes.
Definition: Logging.h:239
IceUtil::Handle< IceGridAdmin >
IceInternal::ProxyHandle<::IceProxy::IceStorm::TopicManager >
ImportExport.h
armarx::aron::type::ObjectPtr
std::shared_ptr< Object > ObjectPtr
Definition: Object.h:36
ARMARXCORE_IMPORT_EXPORT
#define ARMARXCORE_IMPORT_EXPORT
Definition: ImportExport.h:38
IceGrid
Definition: IceManager.cpp:51
Logging.h
armarx::ObjectHandles
std::pair< Ice::ObjectPrx, Ice::ObjectAdapterPtr > ObjectHandles
Object handles pair which contains the object proxy and its adapter.
Definition: IceManager.h:97
armarx
This file offers overloads of toIce() and fromIce() functions for STL container types.
Definition: ArmarXTimeserver.cpp:27