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
38namespace 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&
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
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 */
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
uint8_t data[1]
to retreive a unique Hardware identifier
std::string getHardwareId(const Ice::Current &c=Ice::emptyCurrent) override
Retrieve machine's hardware Id string.
const std::string & getMemoryName() const
TransferMode getTransferMode()
Retrieve transfer mode.
void getData(std::vector< MemoryObject > &data)
void start()
Starts the memory consumer.
void getData(std::vector< MemoryObject > &data, typename MemoryObjectMetaInfo::PointerType &info)
Retrieve the data provided by the IceSharedMemoryProvider.
int getSize() const
Retrieve size of the data.
IceUtil::Handle< IceSharedMemoryConsumer< MemoryObject, MemoryObjectMetaInfo > > pointer_type
pointer type for convenience.
MemoryObjectMetaInfo::PointerType getMetaInfo() const
IceSharedMemoryConsumer(ManagedIceObject *object, std::string providerName, std::string nameSuffix="")
Creates an ice shared memory consumer which transparentely communicates using shared memory on local ...
void setTransferMode(TransferMode mode)
Change the transfer mode.
The ManagedIceObject is the base class for all ArmarX objects.
bool usingProxy(const std::string &name, const std::string &endpoints="")
Registers a proxy for retrieval after initialization and adds it to the dependency list.
The SharedMemoryConsumer opens an existing shared memory segment for reading.
std::shared_ptr< SharedMemoryConsumer< MemoryObject, MemoryObjectMetaInfo > > pointer_type
#define ARMARX_INFO
The normal logging level.
Definition Logging.h:181
#define ARMARX_ERROR_S
The logging level for unexpected behaviour, that must be fixed.
Definition Logging.h:216
#define ARMARX_INFO_S
Definition Logging.h:202
#define ARMARX_WARNING
The logging level for unexpected behaviour, but not a serious problem.
Definition Logging.h:193
#define ARMARX_WARNING_S
The logging level for unexpected behaviour, but not a serious problem.
Definition Logging.h:213
This file offers overloads of toIce() and fromIce() functions for STL container types.
std::string GetHandledExceptionString()
std::shared_ptr< SharedMemoryScopedReadLock > SharedMemoryScopedReadLockPtr
const LogSender::manipulator flush
Definition LogSender.h:251