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 
31 #include <ArmarXCore/interface/core/ManagedIceObjectDefinitions.h>
32 #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  */
64  IceSharedMemoryConsumer(ManagedIceObject* object, std::string providerName, std::string nameSuffix = "")
65  {
66  // member initialization
67  this->object = object;
68  this->providerName = providerName;
69  memoryName = providerName + "Memory" + nameSuffix;
70  transferMode = eSharedMem;
71  // make component dependent on shared memory ice object
72  object->usingProxy(providerName);
73  //object->usingProxy(memoryName);
74  }
75 
76  const std::string& getMemoryName() const
77  {
78  return memoryName;
79  }
80 
81  /**
82  * Starts the memory consumer. The component needs to be connected, otherwise method will fail.
83  *
84  * @throw SharedMemoryException
85  */
86  void start()
87  {
88  if (object->getState() < eManagedIceObjectStarting)
89  {
90  ARMARX_ERROR_S << "Object state is " << object->getState();
91  //throw exceptions::local::SharedMemoryConnectionFailure(memoryName, "Started IceSharedMemoryConsumer before component is in connected state.");
92  }
93 
94  initIce(object->getProxy());
95 
96  // check transfermode
97 
98  if (transferMode == eIce)
99  {
100  ARMARX_INFO_S << "Transfer mode already set. Skipping autodetection";
101  }
102  else if (getHardwareId() == "00:00:00:00:00:00")
103  {
104  transferMode = eIce;
105  ARMARX_WARNING_S << "Unable to determine hardware id. Using ice memory transfer as fallback.";
106  }
107  else if (memoryProxy->getHardwareId() == getHardwareId())
108  {
109  try
110  {
111  initSharedMemory();
112  transferMode = eSharedMem;
113  ARMARX_INFO << "Using shared memory transfer" << flush;
114  }
115  catch (std::exception& e)
116  {
117  transferMode = eIce;
118  ARMARX_WARNING << "Initialization of shared memory '" << providerName << "' failed - failing back to Ice memory transfer - reason: " << e.what();
119  }
120 
121  }
122  else
123  {
124  transferMode = eIce;
125  ARMARX_INFO << "Using Ice memory transfer" << flush;
126  }
127  }
128 
129 
130  void getData(std::vector<MemoryObject>& data)
131  {
132  typename MemoryObjectMetaInfo::PointerType info;
133  getData(data, info);
134  }
135 
136 
137  /**
138  * Retrieve the data provided by the IceSharedMemoryProvider.
139  *
140  * @throw SharedMemoryException
141  */
142  void getData(std::vector<MemoryObject>& data, typename MemoryObjectMetaInfo::PointerType& info)
143  {
144  if (transferMode == eSharedMem)
145  {
146  return getDataSharedMemory(data, info);
147  }
148  else
149  {
150  return getDataIce(data, info);
151  }
152  }
153 
154  typename MemoryObjectMetaInfo::PointerType getMetaInfo() const
155  {
156  if (transferMode == eSharedMem)
157  {
158  // SharedMemoryScopedReadLockPtr lock(sharedMemoryConsumer->getScopedReadLock());
159  typename MemoryObjectMetaInfo::PointerType info = sharedMemoryConsumer->getMetaInfo();
160  return info;
161  }
162  else
163  {
164  return memoryProxy->getMetaInfo();
165  }
166  }
167 
168  /**
169  * Retrieve size of the data
170  *
171  * @return size of the memory in bytes
172  */
173  int getSize() const
174  {
175  if (transferMode == eSharedMem)
176  {
177  return sharedMemoryConsumer->getSize();
178  }
179  else
180  {
181  return memoryProxy->getSize();
182  }
183 
184  }
185 
186  /**
187  * Change the transfer mode.
188  *
189  * @param mode the new transfer mode
190  */
191  void setTransferMode(TransferMode mode)
192  {
193  transferMode = mode;
194  }
195 
196  /**
197  * Retrieve transfer mode
198  *
199  * @return transfer mode
200  */
201  TransferMode getTransferMode()
202  {
203  return transferMode;
204  }
205 
206  /**
207  * pointer type for convenience.
208  */
210 
211  private:
212  /**
213  * init Ice connection. Connects to the remote component that handles the provider.
214  */
215  void initIce(Ice::ObjectPrx providerProxy)
216  {
217  try
218  {
219  memoryProxy = object->getProxy<SharedMemoryProviderInterfacePrx>(memoryName, true);
220  }
221  catch (std::exception& e)
222  {
223  throw exceptions::local::SharedMemoryConnectionFailure(memoryName, "Error retrieving shared memory proxy. An exception occured when calling object->getProxy<SharedMemoryProviderInterfacePrx>():")
224  << "\nOriginal exception: " << e.what();
225 
226  }
227  catch (...)
228  {
229  throw exceptions::local::SharedMemoryConnectionFailure(memoryName, "Error retrieving shared memory proxy. An exception occured when calling object->getProxy<SharedMemoryProviderInterfacePrx>().");
230  }
231 
232  if (!memoryProxy)
233  {
234  throw exceptions::local::SharedMemoryConnectionFailure(memoryName, "Error retrieving shared memory proxy: The returned memory proxy is NULL.");
235  }
236  }
237 
238  /**
239  * init shared memory transfer.
240  */
241  void initSharedMemory()
242  {
243  // create sharedMemoryConsumer. might throw.
244  sharedMemoryConsumer.reset(new SharedMemoryConsumer<MemoryObject, MemoryObjectMetaInfo>(memoryName));
245  }
246 
247  /**
248  * return data via shared memory
249  */
250  void getDataSharedMemory(std::vector<MemoryObject>& data, typename MemoryObjectMetaInfo::PointerType& info)
251  {
252  // lock shared memory
253  SharedMemoryScopedReadLockPtr lock(sharedMemoryConsumer->getScopedReadLock());
254 
255  auto p = this->sharedMemoryConsumer->getMetaInfo(false);
256 
257  if (p)
258  {
259  using Ptr = typename MemoryObjectMetaInfo::PointerType;
260  info = Ptr::dynamicCast(new typename SharedMemoryType::Wrapper(*p));
261  }
262  else
263  {
264  throw exceptions::local::SharedMemoryConnectionFailure(memoryName, "Info pointer is null.");
265  }
266  int size = p->size;
267 
268  data.resize(size);
269  memcpy(data.data(), sharedMemoryConsumer->getMemory(), size);
270  }
271 
272  /**
273  * return data via Ice
274  */
275  void getDataIce(std::vector<MemoryObject>& data, typename MemoryObjectMetaInfo::PointerType& info)
276  {
277  Blob blob;
278  auto baseInfo = MetaInfoSizeBasePtr::dynamicCast(info);
279 
280  if (!baseInfo && info)
281  {
282  throw exceptions::local::SharedMemoryConnectionFailure(memoryName, "Error casting info var to base type.");
283  }
284 
285  // retrieve data
286  try
287  {
288  blob = memoryProxy->getData(baseInfo);
289  if (!baseInfo->size)
290  {
291  return;
292  }
293  data.resize(baseInfo->size);
294  }
295  catch (...)
296  {
297  throw exceptions::local::SharedMemoryConnectionFailure(memoryName, "Error retrieving data from shared memory proxy: " + GetHandledExceptionString());
298  }
299 
300  using Ptr = typename MemoryObjectMetaInfo::PointerType;
301  info = Ptr::dynamicCast(baseInfo);
302 
303  if (!info && baseInfo)
304  {
305  throw exceptions::local::SharedMemoryConnectionFailure(memoryName, "Error casting back info var to desired type.");
306  }
307 
308  memcpy(data.data(), blob.data(), info->size);
309  }
310 
311 
312 
313 
314  private:
315  // memory properties
316  SharedMemoryProviderInterfacePrx memoryProxy;
317  std::string memoryName;
318  std::string providerName;
319 
320  // the shared memory consumer
321  using SharedMemoryType = SharedMemoryConsumer<MemoryObject, MemoryObjectMetaInfo>;
322  typename SharedMemoryType::pointer_type sharedMemoryConsumer;
323 
324  // internals
325  TransferMode transferMode;
326  ManagedIceObject* object;
327  };
328 }
329 
armarx::IceSharedMemoryConsumer::getTransferMode
TransferMode getTransferMode()
Retrieve transfer mode.
Definition: IceSharedMemoryConsumer.h:201
armarx::IceSharedMemoryConsumer::setTransferMode
void setTransferMode(TransferMode mode)
Change the transfer mode.
Definition: IceSharedMemoryConsumer.h:191
armarx::ManagedIceObject::getState
int getState() const
Retrieve current state of the ManagedIceObject.
Definition: ManagedIceObject.cpp:725
armarx::SharedMemoryConsumer
Definition: SharedMemoryConsumer.h:53
armarx::IceSharedMemoryConsumer::getData
void getData(std::vector< MemoryObject > &data, typename MemoryObjectMetaInfo::PointerType &info)
Retrieve the data provided by the IceSharedMemoryProvider.
Definition: IceSharedMemoryConsumer.h:142
armarx::IceSharedMemoryConsumer::start
void start()
Starts the memory consumer.
Definition: IceSharedMemoryConsumer.h:86
armarx::IceSharedMemoryConsumer::getMetaInfo
MemoryObjectMetaInfo::PointerType getMetaInfo() const
Definition: IceSharedMemoryConsumer.h:154
armarx::SharedMemoryScopedReadLockPtr
std::shared_ptr< SharedMemoryScopedReadLock > SharedMemoryScopedReadLockPtr
Definition: SharedMemoryConsumer.h:43
armarx::IceSharedMemoryConsumer::getMemoryName
const std::string & getMemoryName() const
Definition: IceSharedMemoryConsumer.h:76
armarx::GetHandledExceptionString
std::string GetHandledExceptionString()
Definition: Exception.cpp:147
armarx::HardwareIdentifierProvider
Definition: HardwareIdentifierProvider.h:36
SharedMemoryConsumer.h
ManagedIceObject.h
armarx::exceptions::local::SharedMemoryConnectionFailure
Definition: SharedMemoryExceptions.h:49
ARMARX_ERROR_S
#define ARMARX_ERROR_S
Definition: Logging.h:209
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:130
armarx::SharedMemoryConsumer::pointer_type
std::shared_ptr< SharedMemoryConsumer< MemoryObject, MemoryObjectMetaInfo > > pointer_type
Pointer type for convenience.
Definition: SharedMemoryConsumer.h:223
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:206
armarx::IceSharedMemoryConsumer::getSize
int getSize() const
Retrieve size of the data.
Definition: IceSharedMemoryConsumer.h:173
armarx::ManagedIceObject
The ManagedIceObject is the base class for all ArmarX objects.
Definition: ManagedIceObject.h:163
HardwareIdentifierProvider.h
ARMARX_INFO
#define ARMARX_INFO
Definition: Logging.h:174
IceUtil::Handle
Definition: forward_declarations.h:29
SharedMemoryExceptions.h
armarx::IceSharedMemoryConsumer
Definition: IceSharedMemoryConsumer.h:50
ARMARX_INFO_S
#define ARMARX_INFO_S
Definition: Logging.h:195
ARMARX_WARNING
#define ARMARX_WARNING
Definition: Logging.h:186
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:393
armarx
This file offers overloads of toIce() and fromIce() functions for STL container types.
Definition: ArmarXTimeserver.cpp:28
armarx::HardwareIdentifierProvider::getHardwareId
std::string getHardwareId(const Ice::Current &c=Ice::emptyCurrent) override
Retrieve machine's hardware Id string.
Definition: HardwareIdentifierProvider.h:44