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 <ArmarXCore/core/logging/Logging.h> // for Logging
29 #include <ArmarXCore/core/system/ImportExport.h> // for ARMARXCORE_IMPORT_EXPORT
31 
32 #include <Ice/Object.h> // for ObjectPtr
33 #include <Ice/Proxy.h> // for ObjectPrx
34 #include <Ice/Properties.h> // for upCast
35 
36 #include <IceUtil/Handle.h> // for Handle, HandleBase
37 #include <IceUtil/Shared.h> // for Shared
38 
39 #include <stdexcept> // for out_of_range
40 #include <string> // for string, allocator, etc
41 #include <typeinfo> // for type_info
42 #include <utility> // for pair
43 #include <vector> // for vector
44 
45 namespace Ice
46 {
47  class ConnectionRefusedException;
48 
49  class Communicator;
50  typedef ::IceInternal::Handle< ::Ice::Communicator> CommunicatorPtr;
51 
52  class ObjectAdapter;
53  typedef ::IceInternal::Handle< ::Ice::ObjectAdapter> ObjectAdapterPtr;
54 
55 }
56 
58 {
59  class Registry;
60 }
61 namespace IceProxy::IceStorm
62 {
63  class TopicManager;
64  class Topic;
65 }
66 
67 namespace IceStorm
68 {
71 }
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  /**
101  * @class IceManager
102  * @brief The IceManager class provides simplified access to commonly used Ice features.
103  * @ingroup DistributedProcessingSub
104  * @see Logging
105  */
107  public IceUtil::Shared,
108  virtual public Logging
109  {
110  friend class Component;
111 
112  public:
113  /**
114  * Set up an instance of this class with a preexisting communicator.
115  *
116  * This is useful for creating an instance from within an
117  * Ice::Application. If you do not have a communicator yet you can
118  * use one of the static factory methods instead.
119  *
120  * @param communicator An Ice communicator
121  *
122  * @param name A unique name, e.g. the base component's
123  * name. This name is used to create
124  * IceGridObservers, which must have a unique
125  * name.
126  * @param topicSuffix Suffix appended to all topic names.
127  */
128  IceManager(const Ice::CommunicatorPtr& communicator,
129  std::string name = "", const std::string topicSuffix = "");
130 
131  ~IceManager() override;
132 
133  /**
134  * Register an object with Ice for being accessed through IceGrid.
135  *
136  * @param object The object to be registered, implementing an
137  * Ice interface.
138  *
139  * @param objectName The name this object should be available as.
140  *
141  * @return The registered object proxy.
142  */
143  ObjectHandles registerObject(const Ice::ObjectPtr& object,
144  const std::string& objectName, const Ice::ObjectAdapterPtr& adapterToAddTo = nullptr);
145 
146  /**
147  * Removes an object from the IceGrid
148  *
149  * @param objectName The name of the object that should be removed
150  */
151  void removeObject(const std::string& objectName);
152 
153  /**
154  * Retrieves a proxy object.
155  *
156  * @param name Proxy name, e.g. Log
157  * @param endpoints The endpoints, e.g. tcp ‑p 10002
158  *
159  * @return A proxy of the remote instance.
160  */
161  template <class ProxyType>
162  ProxyType getProxy(const std::string& name,
163  const std::string& endpoints = std::string())
164  {
165  std::string proxyString = name;
166 
167  if (!endpoints.empty())
168  {
169  proxyString += std::string(":") + endpoints;
170  }
171 
172  std::string proxyTypedId =
173  proxyString
174  + std::string(":")
175  + std::string(typeid(ProxyType).name());
176 
177  try
178  {
179  return ProxyType::uncheckedCast(implGetCheckedProxy(proxyTypedId));
180  }
181  catch (std::out_of_range& uncheckedProxiesException)
182  {
183  }
184 
185  Ice::ObjectPrx base = communicator_stringToProxy(proxyString);
186 
187  ProxyType proxy;
188 
189  try
190  {
191  proxy = ProxyType::checkedCast(base);
192  implSetCheckedProxy(proxyTypedId, proxy);
193  }
194  catch (const Ice::ConnectionRefusedException&)
195  {
196  std::stringstream exceptionText;
197  exceptionText << "Connection refused for proxy of type '" << GetTypeString<ProxyType>()
198  << "': " << name << " ProxyString: " << proxyString << " Endpoints: " << endpoints << std::endl;
199  throwUserException(exceptionText.str());
200  }
201 
202  if (!proxy)
203  {
204  std::stringstream exceptionText;
205  exceptionText << "Invalid Proxy. Searched for: " << name << " ProxyString: " << proxyString << " Endpoints: " << endpoints << std::endl;
206  throwUserException(exceptionText.str());
207  }
208 
209  return proxy;
210  }
211 
212  void throwUserException(std::string const& message);
213 
214  /**
215  * @brief This functions removes the given proxy from the proxy cache.
216  * This is useful if the cached proxy became invalid.
217  * @param name Proxy name, e.g. Log
218  * @param endpoints The endpoints, e.g. tcp ‑p 10002
219  * @return True, if the proxy was found and removed.
220  */
221  template <class ProxyType>
222  bool removeProxyFromCache(const std::string& name,
223  const std::string& endpoints = std::string())
224  {
225  return removeProxyFromCache(name, typeid(ProxyType).name(), endpoints);
226  }
227 
228  bool removeProxyFromCache(const std::string& name,
229  const std::string& typeName,
230  const std::string& endpoints = std::string());
231 
232  /**
233  * @brief This functions removes the given proxy from the proxy cache.
234  * This is useful if the cached proxy became invalid.
235  * @param name Proxy name, e.g. Log
236  * @param endpoints The endpoints, e.g. tcp ‑p 10002
237  * @return True, if the proxy was found and removed.
238  */
239  bool removeProxyFromCache(const Ice::ObjectPrx& proxy);
240 
241  /**
242  * Provides access to the Ice Storm Topic Manager.
243  * A proxy is created if necessary.
244  *
245  * @return A proxy of the IceStorm TopicManager.
246  */
247  IceStorm::TopicManagerPrx getTopicManager();
248  static IceStorm::TopicManagerPrx GetTopicManager(Ice::CommunicatorPtr communicator);
249 
250  /**
251  * Gets an Ice Storm topic for publishing messages.
252  *
253  * @param topicName The name of the topic to publish on.
254  *
255  * @return A proxy of the topic's remote instance.
256  */
257  template <class TopicProxy>
258  TopicProxy getTopic(const std::string& topicName, bool useUDP = false)
259  {
260  Ice::ObjectPrx pub = __getTopic(topicName, useUDP);
261  TopicProxy castTopic = TopicProxy::uncheckedCast(pub);
262 
263  return castTopic;
264  }
265 
266  /**
267  * Subscribe an object to a particular Ice Storm topic.
268  * If the object is already subscribed to the topic, it will be unsubscribed before.
269  * This is necessary to circumvent the usage from outdated subscriptions due to
270  * unproper exits.
271  *
272  * @param subcriber A proxy of the object to be subscribed,
273  * implementing the interface for listening on this
274  * topic
275  * @param topicName The topic's name
276  * @param orderedPublishing If true, the order of topic calls is ensured. This
277  * might decrease performance.
278  */
279  void subscribeTopic(Ice::ObjectPrx subscriber,
280  const std::string& topicName, bool orderedPublishing = false);
281  void registerAndSubscribeTopic(Ice::ObjectPtr subscriber,
282  const std::string& topicName, bool orderedPublishing = false);
283 
284  /**
285  * Unsubscribe a given subscriber from a given topic
286  *
287  * @param subscriberProxy of the subscriber
288  * @param topicName The name of the subscribed topic.
289  */
290  void unsubscribeTopic(Ice::ObjectPrx subscriberProxy,
291  const std::string& topicName);
292 
293  /**
294  * Registers a specified object that is required before
295  * activating the endpoints.
296  *
297  * @param registrantName Object that has a dependency
298  * @param dependecyObjectName Dependecy object name
299  *
300  *
301  * @throw ObjectAlreadyActiveException
302  */
303  void registerObjectDependency(
304  const std::string& registrantName,
305  const std::string& dependencyObjectName);
306 
307  /**
308  * Registers a delayed topic subscription.
309  *
310  * @param registrantName Registrant object name
311  * @param topicName The topic name that should be subscribed
312  * later on
313  */
314  void registerDelayedTopicSubscription(
315  const std::string& registrantName,
316  const std::string& topicName);
317 
318  /**
319  * Registers a delayed topic retrieval.
320  *
321  * @param registrantName Registrant object name
322  * @param topicName The topic name
323  */
324  void registerDelayedTopicRetrieval(
325  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 
400  Ice::ObjectPrx communicator_stringToProxy(std::string const& proxyString);
401 
402  Ice::ObjectPrx __getTopic(const std::string& topicName, bool useUDP = false);
403 
404  struct ObjectEntry;
405 
406  struct DependencyObjectEntry: public IceUtil::Shared
407  {
408  DependencyObjectEntry(std::string name, Ice::ObjectPrx proxy) :
409  name(name),
410  proxy(proxy),
411  resolved(false)
412  {
413 
414  }
415 
416  std::string name;
417  Ice::ObjectPrx proxy;
418  bool resolved;
419  };
420 
421  using ObjectEntryPtr = IceUtil::Handle<ObjectEntry>;
422  using DependencyObjectEntryPtr = IceUtil::Handle<DependencyObjectEntry>;
423 
424  using TopicList = std::vector<std::string>;
425  using DependencyList = std::vector<DependencyObjectEntryPtr>;
426 
427  /**
428  * Subscribes all topics registered for a delayed subscription
429  */
430  void subscribeTopics(Ice::ObjectPrx subscriber,
431  const TopicList& topics, bool orderedPublishing = false);
432 
433  /**
434  * gets all topics registered for a delayed retrieval
435  */
436  void retrieveTopics(const TopicList& topics);
437 
438  /**
439  * Check the existence of required servants.
440  *
441  * @return True if all servant objects exist, otherise false
442  */
443  void resolveObjectDependencies();
444 
445  /**
446  * Returns the requested object entry if exists, otherwise
447  * a new entry is created and return.
448  *
449  * @param objectName Object name of the entry
450  *
451  * @return Smart pointer of the requested ObjectEntry.
452  */
453  ObjectEntryPtr getOrCreateObjectEntry(const std::string& objectName);
454 
455  /**
456  * Cleans up all current IceStorm connections.
457  */
458  void cleanUp();
459 
460  /**
461  * Retrieves an Ice Storm topic from the topic manager if necessary.
462  * Proxies are cached.
463  *
464  * @param topicName The name of the topic to publish on.
465  *
466  * @return A generic proxy instance of the topic. Has to be cast for
467  * actual messages to be sent.
468  */
469  IceStorm::TopicPrx retrieveTopic(const std::string& topicName);
470 
471  /**
472  * Retrieves an Ice Storm topic from the topic manager if necessary.
473  * Proxies are cached.
474  *
475  * @param topicName The name of the topic to publish on.
476  *
477  * @return A generic proxy instance of the topic. Has to be cast for
478  * actual messages to be sent.
479  *
480  * @deprecated Use IceManager::retrieveTopic() instead
481  */
482  IceStorm::TopicPrx stormTopicRetrieve(const std::string& topicName);
483 
484  Ice::ObjectPrx implGetCheckedProxy(std::string const& proxyTypedId);
485  void implSetCheckedProxy(std::string const& proxyTypedId, Ice::ObjectPrx const& proxy);
486 
487 
488  struct Impl;
489  std::unique_ptr<Impl> impl;
490  };
491 
492 
493  template <typename ProxyType>
494  bool IceManager::isObjectReachable(std::string objectName)
495  {
496  try
497  {
498  ProxyType prx = getProxy<ProxyType>(objectName);
499  prx->ice_timeout(500)->ice_ping();
500  // if ping'able, object is already registered
501  return true;
502  }
503  catch (...)
504  {
505 
506  return false;
507  }
508  }
509 
510 }
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:106
GetTypeString.h
IceProxy::IceGrid
Definition: IceManager.h:57
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:684
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:222
Ice::CommunicatorPtr
::IceInternal::Handle< ::Ice::Communicator > CommunicatorPtr
Definition: IceManager.h:49
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:258
IceProxy::IceStorm
Definition: IceStormInternal.h:381
armarx::ProxyType
ProxyType
Definition: ProxyPropertyDefinition.h:41
armarx::Component
Baseclass for all ArmarX ManagedIceObjects requiring properties.
Definition: Component.h:95
armarx::IceGridAdminPtr
IceUtil::Handle< IceGridAdmin > IceGridAdminPtr
Definition: ArmarXFwd.h:48
Ice
Definition: DBTypes.cpp:64
Ice::ObjectAdapterPtr
::IceInternal::Handle< ::Ice::ObjectAdapter > ObjectAdapterPtr
Definition: IceManager.h:52
armarx::Logging
Base Class for all Logging classes.
Definition: Logging.h:232
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:28