IceSharedMemoryConsumer.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 ArmarX::Core
19  * @author Kai Welke (kai dot welke at kit dot edu)
20  * @date 2012
21  * @copyright http://www.gnu.org/licenses/gpl-2.0.txt
22  * GNU General Public License
23  */
24 
25 #pragma once
26 
27 #include <cassert>
28 
32 #include <ArmarXCore/interface/core/ManagedIceObjectDefinitions.h>
33 #include <ArmarXCore/interface/core/SharedMemory.h>
34 
35 // exceptions
37 
38 namespace armarx
39 {
40  /**
41  * \class IceSharedMemoryConsumer
42  * \ingroup SharedMemory
43  * The IceSharedMemoryConsumer reads data via Ice or shared memory. Whether Ice or shared memory is used for data
44  * transfer is determined based on the hardware id of the machine. The consumer should be constructed in the onInit method
45  * and started in the onStart method. The correct initialization of the provider is guaranteed by
46  * the component dependency mechanism. If shared memory consumers are constructed elsewhere, the user has to assure, that
47  * the remote component is already running.
48  */
49  template <class MemoryObject, class MemoryObjectMetaInfo = MetaInfoSizeBase>
51  virtual public HardwareIdentifierProvider,
52  virtual public SharedMemoryConsumerInterface
53  {
54  public:
55  /**
56  * Creates an ice shared memory consumer which transparentely communicates using shared memory
57  * on local machines and using Ice on remote machines.
58  *
59  * @param component pointer to component
60  * @param providerName name of ice object that provides that owns the IceSharedMemoryProvider
61  *
62  * @throw SharedMemoryException
63  */
65  std::string providerName,
66  std::string nameSuffix = "")
67  {
68  // member initialization
69  this->object = object;
70  this->providerName = providerName;
71  memoryName = providerName + "Memory" + nameSuffix;
72  transferMode = eSharedMem;
73  // make component dependent on shared memory ice object
74  object->usingProxy(providerName);
75  //object->usingProxy(memoryName);
76  }
77 
78  const std::string&
79  getMemoryName() const
80  {
81  return memoryName;
82  }
83 
84  /**
85  * Starts the memory consumer. The component needs to be connected, otherwise method will fail.
86  *
87  * @throw SharedMemoryException
88  */
89  void
91  {
92  if (object->getState() < eManagedIceObjectStarting)
93  {
94  ARMARX_ERROR_S << "Object state is " << object->getState();
95  //throw exceptions::local::SharedMemoryConnectionFailure(memoryName, "Started IceSharedMemoryConsumer before component is in connected state.");
96  }
97 
98  initIce(object->getProxy());
99 
100  // check transfermode
101 
102  if (transferMode == eIce)
103  {
104  ARMARX_INFO_S << "Transfer mode already set. Skipping autodetection";
105  }
106  else if (getHardwareId() == "00:00:00:00:00:00")
107  {
108  transferMode = eIce;
110  << "Unable to determine hardware id. Using ice memory transfer as fallback.";
111  }
112  else if (memoryProxy->getHardwareId() == getHardwareId())
113  {
114  try
115  {
116  initSharedMemory();
117  transferMode = eSharedMem;
118  ARMARX_INFO << "Using shared memory transfer" << flush;
119  }
120  catch (std::exception& e)
121  {
122  transferMode = eIce;
124  << "Initialization of shared memory '" << providerName
125  << "' failed - failing back to Ice memory transfer - reason: " << e.what();
126  }
127  }
128  else
129  {
130  transferMode = eIce;
131  ARMARX_INFO << "Using Ice memory transfer" << flush;
132  }
133  }
134 
135  void
136  getData(std::vector<MemoryObject>& data)
137  {
138  typename MemoryObjectMetaInfo::PointerType info;
139  getData(data, info);
140  }
141 
142  /**
143  * Retrieve the data provided by the IceSharedMemoryProvider.
144  *
145  * @throw SharedMemoryException
146  */
147  void
148  getData(std::vector<MemoryObject>& data, typename MemoryObjectMetaInfo::PointerType& info)
149  {
150  if (transferMode == eSharedMem)
151  {
152  return getDataSharedMemory(data, info);
153  }
154  else
155  {
156  return getDataIce(data, info);
157  }
158  }
159 
160  typename MemoryObjectMetaInfo::PointerType
161  getMetaInfo() const
162  {
163  if (transferMode == eSharedMem)
164  {
165  // SharedMemoryScopedReadLockPtr lock(sharedMemoryConsumer->getScopedReadLock());
166  typename MemoryObjectMetaInfo::PointerType info =
167  sharedMemoryConsumer->getMetaInfo();
168  return info;
169  }
170  else
171  {
172  return memoryProxy->getMetaInfo();
173  }
174  }
175 
176  /**
177  * Retrieve size of the data
178  *
179  * @return size of the memory in bytes
180  */
181  int
182  getSize() const
183  {
184  if (transferMode == eSharedMem)
185  {
186  return sharedMemoryConsumer->getSize();
187  }
188  else
189  {
190  return memoryProxy->getSize();
191  }
192  }
193 
194  /**
195  * Change the transfer mode.
196  *
197  * @param mode the new transfer mode
198  */
199  void
200  setTransferMode(TransferMode mode)
201  {
202  transferMode = mode;
203  }
204 
205  /**
206  * Retrieve transfer mode
207  *
208  * @return transfer mode
209  */
210  TransferMode
212  {
213  return transferMode;
214  }
215 
216  /**
217  * pointer type for convenience.
218  */
219  using pointer_type =
221 
222  private:
223  /**
224  * init Ice connection. Connects to the remote component that handles the provider.
225  */
226  void
227  initIce(Ice::ObjectPrx providerProxy)
228  {
229  try
230  {
231  memoryProxy = object->getProxy<SharedMemoryProviderInterfacePrx>(memoryName, true);
232  }
233  catch (std::exception& e)
234  {
236  memoryName,
237  "Error retrieving shared memory proxy. An exception occured when calling "
238  "object->getProxy<SharedMemoryProviderInterfacePrx>():")
239  << "\nOriginal exception: " << e.what();
240  }
241  catch (...)
242  {
244  memoryName,
245  "Error retrieving shared memory proxy. An exception occured when calling "
246  "object->getProxy<SharedMemoryProviderInterfacePrx>().");
247  }
248 
249  if (!memoryProxy)
250  {
252  memoryName,
253  "Error retrieving shared memory proxy: The returned memory proxy is NULL.");
254  }
255  }
256 
257  /**
258  * init shared memory transfer.
259  */
260  void
261  initSharedMemory()
262  {
263  // create sharedMemoryConsumer. might throw.
264  sharedMemoryConsumer.reset(
266  }
267 
268  /**
269  * return data via shared memory
270  */
271  void
272  getDataSharedMemory(std::vector<MemoryObject>& data,
273  typename MemoryObjectMetaInfo::PointerType& info)
274  {
275  // lock shared memory
276  SharedMemoryScopedReadLockPtr lock(sharedMemoryConsumer->getScopedReadLock());
277 
278  auto p = this->sharedMemoryConsumer->getMetaInfo(false);
279 
280  if (p)
281  {
282  using Ptr = typename MemoryObjectMetaInfo::PointerType;
283  info = Ptr::dynamicCast(new typename SharedMemoryType::Wrapper(*p));
284  }
285  else
286  {
287  throw exceptions::local::SharedMemoryConnectionFailure(memoryName,
288  "Info pointer is null.");
289  }
290  int size = p->size;
291 
292  data.resize(size);
293  memcpy(data.data(), sharedMemoryConsumer->getMemory(), size);
294  }
295 
296  /**
297  * return data via Ice
298  */
299  void
300  getDataIce(std::vector<MemoryObject>& data,
301  typename MemoryObjectMetaInfo::PointerType& info)
302  {
303  Blob blob;
304  auto baseInfo = MetaInfoSizeBasePtr::dynamicCast(info);
305 
306  if (!baseInfo && info)
307  {
308  throw exceptions::local::SharedMemoryConnectionFailure(
309  memoryName, "Error casting info var to base type.");
310  }
311 
312  // retrieve data
313  try
314  {
315  blob = memoryProxy->getData(baseInfo);
316  if (!baseInfo->size)
317  {
318  return;
319  }
320  data.resize(baseInfo->size);
321  }
322  catch (...)
323  {
324  throw exceptions::local::SharedMemoryConnectionFailure(
325  memoryName,
326  "Error retrieving data from shared memory proxy: " +
328  }
329 
330  using Ptr = typename MemoryObjectMetaInfo::PointerType;
331  info = Ptr::dynamicCast(baseInfo);
332 
333  if (!info && baseInfo)
334  {
335  throw exceptions::local::SharedMemoryConnectionFailure(
336  memoryName, "Error casting back info var to desired type.");
337  }
338 
339  memcpy(data.data(), blob.data(), info->size);
340  }
341 
342 
343  private:
344  // memory properties
345  SharedMemoryProviderInterfacePrx memoryProxy;
346  std::string memoryName;
347  std::string providerName;
348 
349  // the shared memory consumer
350  using SharedMemoryType = SharedMemoryConsumer<MemoryObject, MemoryObjectMetaInfo>;
351  typename SharedMemoryType::pointer_type sharedMemoryConsumer;
352 
353  // internals
354  TransferMode transferMode;
355  ManagedIceObject* object;
356  };
357 } // namespace armarx
armarx::IceSharedMemoryConsumer::getTransferMode
TransferMode getTransferMode()
Retrieve transfer mode.
Definition: IceSharedMemoryConsumer.h:211
armarx::IceSharedMemoryConsumer::setTransferMode
void setTransferMode(TransferMode mode)
Change the transfer mode.
Definition: IceSharedMemoryConsumer.h:200
armarx::ManagedIceObject::getState
int getState() const
Retrieve current state of the ManagedIceObject.
Definition: ManagedIceObject.cpp:769
armarx::SharedMemoryConsumer
Definition: SharedMemoryConsumer.h:55
armarx::IceSharedMemoryConsumer::getData
void getData(std::vector< MemoryObject > &data, typename MemoryObjectMetaInfo::PointerType &info)
Retrieve the data provided by the IceSharedMemoryProvider.
Definition: IceSharedMemoryConsumer.h:148
armarx::IceSharedMemoryConsumer::start
void start()
Starts the memory consumer.
Definition: IceSharedMemoryConsumer.h:90
armarx::IceSharedMemoryConsumer::getMetaInfo
MemoryObjectMetaInfo::PointerType getMetaInfo() const
Definition: IceSharedMemoryConsumer.h:161
armarx::SharedMemoryScopedReadLockPtr
std::shared_ptr< SharedMemoryScopedReadLock > SharedMemoryScopedReadLockPtr
Definition: SharedMemoryConsumer.h:45
armarx::IceSharedMemoryConsumer::getMemoryName
const std::string & getMemoryName() const
Definition: IceSharedMemoryConsumer.h:79
armarx::GetHandledExceptionString
std::string GetHandledExceptionString()
Definition: Exception.cpp:165
armarx::HardwareIdentifierProvider
Definition: HardwareIdentifierProvider.h:36
SharedMemoryConsumer.h
armarx::IceSharedMemoryConsumer::pointer_type
IceUtil::Handle< IceSharedMemoryConsumer< MemoryObject, MemoryObjectMetaInfo > > pointer_type
pointer type for convenience.
Definition: IceSharedMemoryConsumer.h:220
ManagedIceObject.h
armarx::exceptions::local::SharedMemoryConnectionFailure
Definition: SharedMemoryExceptions.h:53
ARMARX_ERROR_S
#define ARMARX_ERROR_S
Definition: Logging.h:216
armarx::flush
const LogSender::manipulator flush
Definition: LogSender.h:251
data
uint8_t data[1]
Definition: EtherCATFrame.h:68
armarx::IceSharedMemoryConsumer::getData
void getData(std::vector< MemoryObject > &data)
Definition: IceSharedMemoryConsumer.h:136
armarx::SharedMemoryConsumer::pointer_type
std::shared_ptr< SharedMemoryConsumer< MemoryObject, MemoryObjectMetaInfo > > pointer_type
Pointer type for convenience.
Definition: SharedMemoryConsumer.h:245
armarx::IceSharedMemoryConsumer::IceSharedMemoryConsumer
IceSharedMemoryConsumer(ManagedIceObject *object, std::string providerName, std::string nameSuffix="")
Creates an ice shared memory consumer which transparentely communicates using shared memory on local ...
Definition: IceSharedMemoryConsumer.h:64
ARMARX_WARNING_S
#define ARMARX_WARNING_S
Definition: Logging.h:213
armarx::IceSharedMemoryConsumer::getSize
int getSize() const
Retrieve size of the data.
Definition: IceSharedMemoryConsumer.h:182
armarx::ManagedIceObject
The ManagedIceObject is the base class for all ArmarX objects.
Definition: ManagedIceObject.h:162
HardwareIdentifierProvider.h
ARMARX_INFO
#define ARMARX_INFO
Definition: Logging.h:181
IceUtil::Handle
Definition: forward_declarations.h:30
SharedMemoryExceptions.h
armarx::IceSharedMemoryConsumer
Definition: IceSharedMemoryConsumer.h:50
ARMARX_INFO_S
#define ARMARX_INFO_S
Definition: Logging.h:202
ARMARX_WARNING
#define ARMARX_WARNING
Definition: Logging.h:193
armarx::ManagedIceObject::getProxy
Ice::ObjectPrx getProxy(long timeoutMs=0, bool waitForScheduler=true) const
Returns the proxy of this object (optionally it waits for the proxy)
Definition: ManagedIceObject.cpp:407
armarx
This file offers overloads of toIce() and fromIce() functions for STL container types.
Definition: ArmarXTimeserver.cpp:27
armarx::HardwareIdentifierProvider::getHardwareId
std::string getHardwareId(const Ice::Current &c=Ice::emptyCurrent) override
Retrieve machine's hardware Id string.
Definition: HardwareIdentifierProvider.h:44