IceManager.cpp
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#include "IceManager.h"
27
28#include <Ice/Current.h> // for Current
29#include <Ice/DispatchInterceptor.h> // for DispatchInterceptor, etc
30#include <Ice/Initialize.h> // for stringToIdentity
31#include <Ice/LocalException.h> // for AlreadyRegisteredException, etc
32#include <Ice/Object.h> // for DispatchStatus, Object, etc
33#include <Ice/ObjectAdapter.h> // for ObjectAdapterPtr, etc
34#include <Ice/ProxyHandle.h> // for ProxyHandle
35#include <IceGrid/Admin.h> // for AdminPrx, Admin
36#include <IceGrid/Registry.h> // for RegistryPrx
37#include <IceStorm/IceStorm.h> // for TopicPrx, TopicManagerPrx, etc
38#include <IceUtil/Thread.h> // for ThreadControl
39#include <IceUtil/Time.h> // for Time
40#include <IceUtil/UUID.h> // for Time
41
42#include <ArmarXCore/core/IceGridAdmin.h> // for IceGridAdmin
44#include <ArmarXCore/core/logging/LogSender.h> // for LogSender, flush
45#include <ArmarXCore/core/logging/Logging.h> // for ARMARX_INFO, etc
46#include <ArmarXCore/interface/core/UserException.h> // for UserException
47
48#include "IceGridAdmin.h" // for IceGridAdmin
49#include "IceManagerImpl.h"
50
51namespace IceGrid
52{
53 class DeploymentException;
54 class ObjectNotRegisteredException;
55} // namespace IceGrid
56
57namespace armarx
58{
60 std::string name,
61 const std::string topicSuffix) :
62 impl(new Impl)
63 {
64 impl->communicator = communicator;
65 impl->name = name;
66 impl->topicSuffix = topicSuffix;
67 impl->forceShutdown = false;
68 setTag("IceManager");
69 }
70
75
76 class ExeceptionHandlingInterceptor : public Ice::DispatchInterceptor
77 {
78 public:
79 ExeceptionHandlingInterceptor(const Ice::ObjectPtr& servant) : _servant(servant)
80 {
81 }
82
83 bool
84 dispatch(Ice::Request& request) override
85 {
86 try
87 {
88 return _servant->ice_dispatch(request);
89 }
90 catch (...)
91 {
92
94 request.getCurrent().operation +
95 request.getCurrent().id.name)
96 << "Calling interface function '" << request.getCurrent().operation
97 << "' of object '" << request.getCurrent().id.name << "' failed:\n"
99 throw;
100 }
101 }
102
103 Ice::ObjectPtr _servant;
104 };
105
107 IceManager::registerObject(const Ice::ObjectPtr& object,
108 const std::string& objectName,
109 const Ice::ObjectAdapterPtr& adapterToAddTo)
110 {
111 std::unique_lock lock(impl->objectRegistryMutex);
112
113 if (isObjectReachable(objectName))
114 {
115 throw Ice::AlreadyRegisteredException(__FILE__, __LINE__, object->ice_id(), objectName);
116 }
117
118 ObjectEntryPtr objectEntry = getOrCreateObjectEntry(objectName);
119
120 objectEntry->id = Ice::stringToIdentity(objectName);
121
122 if (adapterToAddTo)
123 {
124 objectEntry->adapter = adapterToAddTo;
125 objectEntry->ownAdapter = false;
126 }
127 else
128 {
129 objectEntry->adapter =
130 getCommunicator()->createObjectAdapterWithEndpoints(objectName, "tcp");
131 objectEntry->adapter->activate();
132 objectEntry->ownAdapter = true;
133 }
134
135
136 Ice::DispatchInterceptorPtr interceptor = new ExeceptionHandlingInterceptor(object);
137 objectEntry->adapter->add(interceptor, objectEntry->id);
138 objectEntry->proxy = objectEntry->adapter->createProxy(objectEntry->id);
139
140
141 ARMARX_VERBOSE << objectEntry->name << " registered" << flush;
142
143 return ObjectHandles(objectEntry->proxy, objectEntry->adapter);
144 }
145
146 void
147 IceManager::removeObject(const std::string& objectName)
148 {
149 IceGrid::AdminPrx admin = getIceGridSession()->getAdmin();
150
151 std::unique_lock lock(impl->objectRegistryMutex);
152 {
153 auto objectIt = impl->objectRegistry.find(objectName);
154
155 if (objectIt != impl->objectRegistry.end())
156 {
157 try
158 {
159 ObjectEntryPtr objectEntry = objectIt->second;
160 Ice::ObjectAdapterPtr adapter = objectIt->second->adapter;
161
162 for (auto& topic : objectEntry->usedTopics)
163 {
164 unsubscribeTopic(objectEntry->proxy, topic);
165 }
166
167 if (adapter)
168 {
169 if (objectEntry->ownAdapter)
170 {
171 adapter->destroy();
172 }
173 else if (!adapter->isDeactivated())
174 {
175 adapter->remove(objectEntry->id);
176 }
177 }
178
179
180 // objectIt->second->adapter->remove(objectIt->second->id); // deactivate object adapter
181 ARMARX_VERBOSE << "removing object from ice: " << objectName
182 << " with id: " << objectIt->second->id.name;
183 admin->removeObject(objectIt->second->id);
184 }
185 catch (IceGrid::ObjectNotRegisteredException& notRegisteredException)
186 {
187 // removing an unregistered object
188 // //!!!
189 // ARMARX_ERROR << "*** ARMARX_ERROR: IceManager >> removing "
190 // << objectName
191 // << " object failed due to ObjectNotRegisteredException"
192 // << flush;
193 }
194 catch (IceGrid::DeploymentException& deploymentException)
195 {
196 // cannot remove object due to deployment
197 ARMARX_ERROR << "*** removing " << objectName
198 << " object failed due to DeploymentException" << flush;
199 }
200 catch (Ice::ObjectAdapterDeactivatedException& e)
201 {
202 ARMARX_INFO << "ObjectAdapterDeactivatedException for "
203 << objectIt->second->id.name;
204 }
205
206 impl->objectRegistry.erase(objectIt);
207 }
208 }
209 }
210
211 void
212 IceManager::throwUserException(const std::string& message)
213 {
214 throw armarx::UserException(message);
215 }
216
217 bool
218 IceManager::removeProxyFromCache(const std::string& name,
219 const std::string& typeName,
220 const std::string& endpoints)
221 {
222 std::string proxyString = name;
223
224 if (!endpoints.empty())
225 {
226 proxyString += std::string(":") + endpoints;
227 }
228
229 std::string proxyTypedId = proxyString + std::string(":") + typeName;
230 return (impl->checkedProxies.erase(proxyTypedId) > 0);
231 }
232
233 bool
234 IceManager::removeProxyFromCache(const Ice::ObjectPrx& proxy)
235 {
236 if (!proxy)
237 {
238 return false;
239 }
240 for (auto& proxyEntry : impl->checkedProxies)
241 {
242 if (proxyEntry.second == proxy)
243 {
244 impl->checkedProxies.erase(proxyEntry.first);
245 return true;
246 }
247 }
248 return false;
249 }
250
253 {
254 std::unique_lock lock(impl->topicManagerMutex);
255
256 if (!impl->topicManagerProxy)
257 {
258 impl->topicManagerProxy = GetTopicManager(getCommunicator());
259 }
260
261 return impl->topicManagerProxy;
262 }
263
266 {
267 Ice::ObjectPrx obj = communicator->stringToProxy("IceStorm/TopicManager");
268
269 return IceStorm::TopicManagerPrx::checkedCast(obj);
270 }
271
272 void
273 IceManager::subscribeTopic(Ice::ObjectPrx subscriberProxy,
274 const std::string& topicName,
275 bool orderedPublishing)
276 {
277 IceStorm::TopicPrx topic = retrieveTopic(topicName);
278
279 IceStorm::QoS qos;
280 // // ensure ordered. If CPU is heavily used, the messages might arrive out of sequence even with one publisher if not enabled
281 // // might be a performance issue. But as long as this is not proved leave ordered in order to prevent unexpected behavior (as publishers would assume blocking calls)
282 if (orderedPublishing)
283 {
284 qos["reliability"] = "ordered";
285 }
286
287 try
288 {
289 topic->subscribeAndGetPublisher(
290 qos, orderedPublishing ? subscriberProxy : subscriberProxy->ice_oneway());
291 }
292 catch (IceStorm::AlreadySubscribed& e)
293 {
294 try
295 {
296 unsubscribeTopic(subscriberProxy, topicName);
297 topic->subscribeAndGetPublisher(
298 qos, orderedPublishing ? subscriberProxy : subscriberProxy->ice_oneway());
299 }
300 catch (IceStorm::AlreadySubscribed& e)
301 {
302 ARMARX_INFO << topicName << " already subscribed" << flush;
303 }
304 }
305
306 ARMARX_INFO << "Subscribed to topic " << topicName;
307 std::unique_lock lock(impl->topicSubscriptionMutex);
308 {
309 impl->subscriptions.push_back(std::make_pair(topicName, subscriberProxy));
310 }
311 }
312
313 void
314 IceManager::registerAndSubscribeTopic(Ice::ObjectPtr subscriber,
315 const std::string& topicName,
316 bool orderedPublishing)
317 {
318 auto prx = registerObject(subscriber, topicName + "Listener" + IceUtil::generateUUID());
319 subscribeTopic(prx.first, topicName, orderedPublishing);
320 }
321
322 void
323 IceManager::unsubscribeTopic(Ice::ObjectPrx subscriberProxy, const std::string& topicName)
324 {
325 IceStorm::TopicPrx topic = retrieveTopic(topicName);
326
327 topic->unsubscribe(subscriberProxy);
328 ARMARX_INFO << "Unsubscribed from topic " << topicName;
329 std::unique_lock lock(impl->topicSubscriptionMutex);
330 {
331 std::vector<std::pair<std::string, Ice::ObjectPrx>>::iterator toDelete =
332 impl->subscriptions.end();
333 std::vector<std::pair<std::string, Ice::ObjectPrx>>::iterator it;
334
335 for (it = impl->subscriptions.begin(); it != impl->subscriptions.end(); ++it)
336 {
337 if (it->first == topicName && it->second == subscriberProxy)
338 {
339 toDelete = it;
340 }
341 }
342
343 // we have to check because an old component which is not in our list might still be subscribed
344 if (toDelete != impl->subscriptions.end())
345 {
346 impl->subscriptions.erase(toDelete);
347 }
348 }
349 }
350
352 IceManager::retrieveTopic(const std::string& name)
353 {
354 auto topicName = name + getTopicSuffix();
355 std::unique_lock lock(impl->topicRetrievalMutex);
356
357 IceStorm::TopicPrx& topic = impl->topics[topicName];
358
359 while (!isShutdown() && !topic)
360 {
361 try
362 {
363 topic = getTopicManager()->retrieve(topicName);
364 }
365 catch (const IceStorm::NoSuchTopic&)
366 {
367 try
368 {
369 //this also adds to the map
370 topic = getTopicManager()->create(topicName);
371 ARMARX_INFO << "Topic " << topicName << " created " << flush;
372 }
373 catch (const IceStorm::TopicExists&)
374 {
375 // if the topic has been created in the meanwhile (retry via while)
376 }
377 }
378 }
379
380 return topic;
381 }
382
383 Ice::ObjectPrx
384 IceManager::implGetCheckedProxy(std::string const& proxyTypedId)
385 {
386 std::unique_lock lock(impl->proxyCacheMutex);
387 return impl->checkedProxies.at(proxyTypedId);
388 }
389
390 void
391 IceManager::implSetCheckedProxy(std::string const& proxyTypedId, const Ice::ObjectPrx& proxy)
392 {
393 std::unique_lock lock(impl->proxyCacheMutex);
394 impl->checkedProxies[proxyTypedId] = proxy;
395 }
396
397 void
399 {
400 cleanUp();
401
402 getCommunicator()->shutdown();
403 }
404
405 void
407 {
408 getCommunicator()->waitForShutdown();
409 }
410
411 bool
413 {
414 return getCommunicator()->isShutdown();
415 }
416
417 void
419 {
420 if (impl->iceGridAdmin)
421 {
422 impl->iceGridAdmin->stop();
423 }
424
425 getCommunicator()->destroy();
426 }
427
428 std::string
430 {
431 return impl->topicSuffix;
432 }
433
434 Ice::ObjectPrx
435 IceManager::communicator_stringToProxy(const std::string& proxyString)
436 {
437 return getCommunicator()->stringToProxy(proxyString);
438 }
439
440 Ice::ObjectPrx
441 IceManager::__getTopic(const std::string& topicName, bool useUDP)
442 {
443 IceStorm::TopicPrx topic = retrieveTopic(topicName);
444
445 auto prx = topic->getPublisher();
446 if (useUDP)
447 {
448 prx = prx->ice_datagram();
449 }
450 else
451 {
452 prx = prx->ice_oneway();
453 }
454 return prx;
455 }
456
457 void
458 IceManager::cleanUp()
459 {
460 ARMARX_DEBUG << " *** CLEAN UP ***" << flush;
461
462 // unsubscribe all and remove all objects
463 if (getCommunicator())
464 {
465 IceGrid::AdminPrx admin = getIceGridSession()->getAdmin();
466 std::vector<std::pair<std::string, Ice::ObjectPrx>>::iterator it;
467
468 {
469 /* topicSubscription lock scope */
470 std::unique_lock lock(impl->topicSubscriptionMutex);
471 {
472 for (it = impl->subscriptions.begin(); it != impl->subscriptions.end(); ++it)
473 {
474 retrieveTopic(it->first)->unsubscribe(it->second);
475 }
476
477 impl->subscriptions.clear();
478 }
479 }
480
481 std::unique_lock lock(impl->objectRegistryMutex);
482 {
483 auto objListIt = impl->objectRegistry.begin();
484
485 for (; objListIt != impl->objectRegistry.end(); ++objListIt)
486 {
487 try
488 {
489 objListIt->second->adapter->deactivate();
490 // objListIt->second->adapter->remove(objListIt->second->id); // deactivate object adapter
491 admin->removeObject(objListIt->second->id);
492 }
493 catch (...)
494 {
495 }
496 }
497 }
498
499 if (impl->iceGridAdmin)
500 {
501 impl->iceGridAdmin->removeObservers();
502 }
503 }
504 }
505
506 void
507 IceManager::registerObjectDependency(const std::string& registrantName,
508 const std::string& dependencyObjectName)
509 {
510 std::unique_lock lock(impl->objectRegistryMutex);
511 {
512 ObjectEntryPtr objectEntry = getOrCreateObjectEntry(registrantName);
513
514 objectEntry->dependencies.push_back(new DependencyObjectEntry(
515 dependencyObjectName, getCommunicator()->stringToProxy(dependencyObjectName)));
516 }
517 }
518
519 void
520 IceManager::resolveObjectDependencies()
521 {
522 auto objectIt = impl->objectRegistry.begin();
523
524 for (; objectIt != impl->objectRegistry.end(); ++objectIt)
525 {
526 std::string missingObjects;
527 ObjectEntryPtr objectEntry = objectIt->second;
528
529 if (!objectEntry->active && objectEntry->proxy)
530 {
531 objectEntry->dependenciesResolved = true;
532 DependencyList::iterator depIt = objectEntry->dependencies.begin();
533
534 for (; depIt != objectEntry->dependencies.end(); ++depIt)
535 {
536 DependencyObjectEntryPtr dependencyEntry = *depIt;
537
538 if (!dependencyEntry->resolved)
539 {
540 try
541 {
542 dependencyEntry->proxy->ice_timeout(2000)->ice_ping();
543
544 ARMARX_INFO << objectEntry->name << " found " << dependencyEntry->name
545 << flush;
546
547 dependencyEntry->resolved = true;
548
549 objectEntry->updated = true;
550 }
551 catch (...)
552 {
553 objectEntry->dependenciesResolved = false;
554
555 missingObjects += "\t" + dependencyEntry->name + "\n";
556 }
557
558 IceUtil::ThreadControl::sleep(IceUtil::Time::milliSeconds(10));
559 }
560 }
561 }
562
563 if (objectEntry->updated)
564 {
565 if (missingObjects.length() > 0)
566 {
567 ARMARX_INFO << objectEntry->name << " still waiting for:\n"
568 << missingObjects << flush;
569 }
570
571 objectEntry->updated = false;
572
573 if (objectEntry->dependenciesResolved)
574 {
575 ARMARX_INFO << " all " << objectEntry->name << " dependencies resolved"
576 << flush;
577 }
578 }
579 }
580 }
581
582 void
583 IceManager::registerDelayedTopicSubscription(const std::string& registrantName,
584 const std::string& topicName)
585 {
586 std::unique_lock lock(impl->objectRegistryMutex);
587
588 ObjectEntryPtr objectEntry = getOrCreateObjectEntry(registrantName);
589
590 objectEntry->usedTopics.push_back(topicName);
591 }
592
593 void
594 IceManager::registerDelayedTopicRetrieval(const std::string& registrantName,
595 const std::string& topicName)
596 {
597 std::unique_lock lock(impl->objectRegistryMutex);
598
599 ObjectEntryPtr objectEntry = getOrCreateObjectEntry(registrantName);
600
601 objectEntry->offeredTopics.push_back(topicName);
602 }
603
604 void
605 IceManager::subscribeTopics(Ice::ObjectPrx subscriber,
606 const TopicList& topics,
607 bool orderedPublishing)
608 {
609 TopicList::const_iterator it = topics.begin();
610
611 for (; it != topics.end(); ++it)
612 {
613 subscribeTopic(subscriber, *it, orderedPublishing);
614 }
615 }
616
617 void
618 IceManager::retrieveTopics(const TopicList& topics)
619 {
620 TopicList::const_iterator it = topics.begin();
621
622 for (; it != topics.end(); ++it)
623 {
624 retrieveTopic(*it);
625 }
626 }
627
628 void
629 IceManager::setName(std::string name)
630 {
631 this->impl->name = name;
632 }
633
636 {
637 return impl->communicator;
638 }
639
640 const IceGridAdminPtr&
642 {
643 std::unique_lock lock(impl->iceGridAdminMutex);
644
645 if (!impl->iceGridAdmin)
646 {
647 impl->iceGridAdmin = IceGridAdmin::Create(getCommunicator(), impl->name);
648 }
649
650 return impl->iceGridAdmin;
651 }
652
655 {
656 return getIceGridSession()->registry();
657 }
658
659 IceManager::ObjectEntryPtr
660 IceManager::getOrCreateObjectEntry(const std::string& objectName)
661 {
662 auto objIt = impl->objectRegistry.find(objectName);
663
664 if (objIt == impl->objectRegistry.end() || objIt->second->name.empty())
665 {
666 ObjectEntryPtr objectEntry = new ObjectEntry();
667 objectEntry->name = objectName;
668
669 impl->objectRegistry[objectName] = objectEntry;
670
671 return objectEntry;
672 }
673
674 return objIt->second;
675 }
676
677 bool
678 IceManager::isObjectReachable(std::string objectName)
679 {
680 try
681 {
682 Ice::ObjectPrx prx = getProxy<Ice::ObjectPrx>(objectName);
683 prx->ice_timeout(500)->ice_ping();
684 return true; // if ping'able, object is already registered
685 // throw Ice::AlreadyRegisteredException(__FILE__,__LINE__, object->ice_id(), object->getName());
686 }
687 catch (...)
688 {
689
690 return false;
691 }
692 }
693} // namespace armarx
SpamFilterDataPtr deactivateSpam(SpamFilterDataPtr const &spamFilter, float deactivationDurationSec, const std::string &identifier, bool deactivate)
Definition Logging.cpp:75
ExeceptionHandlingInterceptor(const Ice::ObjectPtr &servant)
bool dispatch(Ice::Request &request) override
std::string getTopicSuffix() const
Get the suffix that is appended to all topics.
void subscribeTopic(Ice::ObjectPrx subscriber, const std::string &topicName, bool orderedPublishing=false)
Subscribe an object to a particular Ice Storm topic.
const Ice::CommunicatorPtr & getCommunicator()
Short helper method to return the Ice Communicator.
void unsubscribeTopic(Ice::ObjectPrx subscriberProxy, const std::string &topicName)
Unsubscribe a given subscriber from a given topic.
void registerObjectDependency(const std::string &registrantName, const std::string &dependencyObjectName)
Registers a specified object that is required before activating the endpoints.
void destroy()
Destroys the communicator.
void waitForShutdown()
Waits until all invoked operation has been processed.
IceStorm::TopicManagerPrx getTopicManager()
Provides access to the Ice Storm Topic Manager.
void shutdown()
Removes all component objects and topics and shuts down the communicator.
ObjectHandles registerObject(const Ice::ObjectPtr &object, const std::string &objectName, const Ice::ObjectAdapterPtr &adapterToAddTo=nullptr)
Register an object with Ice for being accessed through IceGrid.
void throwUserException(std::string const &message)
void registerDelayedTopicSubscription(const std::string &registrantName, const std::string &topicName)
Registers a delayed topic subscription.
static IceStorm::TopicManagerPrx GetTopicManager(Ice::CommunicatorPtr communicator)
bool isObjectReachable(std::string objectName)
creates a proxy to the object specified with parameter objectName and tries to ping it.
bool isShutdown()
Determines whether the communicator is shutdown.
IceGrid::RegistryPrx getIceGridRegistry()
Provides access to the IceGrid Registry.
IceManager(const Ice::CommunicatorPtr &communicator, std::string name="", const std::string topicSuffix="")
Set up an instance of this class with a preexisting communicator.
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
~IceManager() override
void setName(std::string name)
Sets the session name.
void registerDelayedTopicRetrieval(const std::string &registrantName, const std::string &topicName)
Registers a delayed topic retrieval.
ProxyType getProxy(const std::string &name, const std::string &endpoints=std::string())
Retrieves a proxy object.
Definition IceManager.h:162
void removeObject(const std::string &objectName)
Removes an object from the IceGrid.
const armarx::IceGridAdminPtr & getIceGridSession()
Provides access to the IceGrid AdminSession via IceGridAdmin.
void registerAndSubscribeTopic(Ice::ObjectPtr subscriber, const std::string &topicName, bool orderedPublishing=false)
void setTag(const LogTag &tag)
Definition Logging.cpp:54
#define ARMARX_INFO
The normal logging level.
Definition Logging.h:181
#define ARMARX_ERROR
The logging level for unexpected behaviour, that must be fixed.
Definition Logging.h:196
#define ARMARX_DEBUG
The logging level for output that is only interesting while debugging.
Definition Logging.h:184
#define ARMARX_WARNING
The logging level for unexpected behaviour, but not a serious problem.
Definition Logging.h:193
#define ARMARX_VERBOSE
The logging level for verbose information.
Definition Logging.h:187
::IceInternal::ProxyHandle<::IceProxy::IceGrid::Registry > RegistryPrx
Definition IceManager.h:75
::IceInternal::ProxyHandle<::IceProxy::IceStorm::Topic > TopicPrx
Definition IceManager.h:70
::IceInternal::ProxyHandle<::IceProxy::IceStorm::TopicManager > TopicManagerPrx
Definition IceManager.h:69
::IceInternal::Handle<::Ice::Communicator > CommunicatorPtr
Definition IceManager.h:49
::IceInternal::Handle<::Ice::ObjectAdapter > ObjectAdapterPtr
Definition IceManager.h:52
This file offers overloads of toIce() and fromIce() functions for STL container types.
std::pair< Ice::ObjectPrx, Ice::ObjectAdapterPtr > ObjectHandles
Object handles pair which contains the object proxy and its adapter.
Definition IceManager.h:97
std::string GetHandledExceptionString()
IceUtil::Handle< IceGridAdmin > IceGridAdminPtr
Definition ArmarXFwd.h:48
const LogSender::manipulator flush
Definition LogSender.h:251