RestPersistence.cpp
Go to the documentation of this file.
2
4
6{
7
8 const std::string RestPersistence::DEFAULT_HOST = "localhost";
9
10 std::vector<std::string>
12 {
13 if (!enabled_)
14 {
15 ARMARX_DEBUG << "Rest strategy " << identifier_ << " disabled. Aborting call.";
16
17 return std::vector<std::string>();
18 }
19
20 return getRestContainers(id);
21 }
22
23 std::vector<std::string>
25 {
26 if (!enabled_)
27 {
28 ARMARX_DEBUG << "Rest strategy " << identifier_ << " disabled. Aborting call.";
29
30 return std::vector<std::string>();
31 }
32
33 return getRestItems(id);
34 }
35
36 bool
38 {
39 if (!enabled_)
40 {
41 ARMARX_DEBUG << "Rest strategy " << identifier_ << " disabled. Aborting call.";
42
43 return false;
44 }
45
46 return restContainsContainer(id, key);
47 }
48
49 bool
51 {
52 if (!enabled_)
53 {
54 ARMARX_DEBUG << "Rest strategy " << identifier_ << " disabled. Aborting call.";
55
56 return false;
57 }
58
59 return restContainsItem(id, key);
60 }
61
62 void
64 std::string key,
65 std::vector<unsigned char>& data)
66 {
67 if (!enabled_)
68 {
69 ARMARX_DEBUG << "Rest strategy " << identifier_ << " disabled. Aborting call.";
70
71 return;
72 }
73
74 writeItemToRest(id, key, data);
75 }
76
77 std::vector<unsigned char>
79 {
80 if (!enabled_)
81 {
82 ARMARX_DEBUG << "Rest strategy " << identifier_ << " disabled. Aborting call.";
83
84 return std::vector<unsigned char>();
85 }
86
87 if (containsItem(id, key))
88 {
89 return readItemFromRest(id, key);
90 }
91
92 return std::vector<unsigned char>();
93 }
94
95 void
97 const std::string& prefix)
98 {
99 defs->optional(host_, prefix + "host");
100 defs->optional(port_, prefix + "port");
101 }
102
103 bool
105 {
106 std::string path = "/ltm";
107
108 auto res = client_->Get(path);
109
110 if (res)
111 {
112 ARMARX_IMPORTANT << "MemoryX-REST server is running at host=" << host_
113 << ", port=" << port_;
114
115 return true;
116 }
117
118 ARMARX_IMPORTANT << "MemoryX-REST server is not running at host=" << host_
119 << ", port=" << port_;
120
121 return false;
122 }
123
124 void
125 RestPersistence::resetClient()
126 {
127 if (client_)
128 {
129 client_->stop();
130 }
131
132 client_ = std::make_shared<httplib::Client>(host_, port_);
133 }
134
135 bool
136 RestPersistence::restContainsItem(const armarx::armem::MemoryID& id, std::string& key)
137 {
138 std::string path = buildPath(id);
139 std::string query = "item=" + key;
140 std::string url = path + "?" + query;
141
142 ARMARX_DEBUG << "GET request: Read data from MemoryX-REST server: item=" << key
143 << ", url=" << url;
144
145 auto res = client_->Get(url);
146
147 bool containsItem = false;
148
149 if (res && res->status == httplib::StatusCode::OK_200)
150 {
151 ARMARX_DEBUG << "GET request successful: REST-LTM contain item with key=" << key;
152 ARMARX_DEBUG << "Response: " << res->body;
153
154 containsItem = true;
155 }
156 else if (res && res->status == httplib::StatusCode::NotFound_404)
157 {
158 ARMARX_DEBUG << "GET request successful: REST-LTM does not contain item with key="
159 << key;
160 ARMARX_DEBUG << "Response: " << res->body;
161
162 containsItem = false;
163 }
164 else if (res)
165 {
166 ARMARX_DEBUG << "GET request failed. Status: " << res->status;
167 ARMARX_DEBUG << "Response: " << res->body;
168 }
169 else
170 {
171 ARMARX_DEBUG << "GET request failed. No connection could be established to the "
172 "MemoryX-REST server at host="
173 << host_ << ", port=" << port_;
174 }
175
176 return containsItem;
177 }
178
179 bool
180 RestPersistence::restContainsContainer(const armarx::armem::MemoryID& id, std::string& key)
181 {
182 std::string path = buildPath(id);
183 std::string query = "container=" + key;
184 std::string url = path + "?" + query;
185
186 ARMARX_DEBUG << "GET request: Read data from MemoryX-REST server: container=" << key
187 << ", url=" << url;
188
189 auto res = client_->Get(url);
190
191 bool containsContainer = false;
192
193 if (res && res->status == httplib::StatusCode::OK_200)
194 {
195 ARMARX_DEBUG << "GET request successful: REST-LTM contain container with key=" << key;
196 ARMARX_DEBUG << "Response: " << res->body;
197
198 containsContainer = true;
199 }
200 else if (res && res->status == httplib::StatusCode::NotFound_404)
201 {
202 ARMARX_DEBUG << "GET request successful: REST-LTM does not contain container with key="
203 << key;
204 ARMARX_DEBUG << "Response: " << res->body;
205
206 containsContainer = false;
207 }
208 else if (res)
209 {
210 ARMARX_DEBUG << "GET request failed. Status: " << res->status;
211 ARMARX_DEBUG << "Response: " << res->body;
212 }
213 else
214 {
215 ARMARX_DEBUG << "GET request failed. No connection could be established to the "
216 "MemoryX-REST server at host="
217 << host_ << ", port=" << port_;
218 }
219
220 return containsContainer;
221 }
222
223 std::vector<std::string>
224 RestPersistence::getRestItems(const armarx::armem::MemoryID& id)
225 {
226 std::string path = buildPath(id);
227 std::string query = "items";
228 std::string url = path + "?" + query;
229
230 ARMARX_DEBUG << "GET request: Get items from MemoryX-REST server: url=" << url;
231
232 auto res = client_->Get(url);
233
234 std::vector<std::string> item_keys;
235
236 if (res && res->status == httplib::StatusCode::OK_200)
237 {
238 ARMARX_DEBUG << "GET request response: " << res->body;
239
240 try
241 {
242 nlohmann::json json_response = nlohmann::json::parse(res->body);
243
244 if (json_response.contains("keys") && json_response["keys"].is_array())
245 {
246 item_keys = json_response["keys"].get<std::vector<std::string>>();
247 }
248 }
249 catch (const std::exception& e)
250 {
251 ARMARX_DEBUG << "GET request: Error parsing JSON: " << e.what();
252 }
253 }
254 else if (res)
255 {
256 ARMARX_DEBUG << "GET request failed. status=" << res->status << ", url=" << url;
257 }
258 else
259 {
260 ARMARX_DEBUG << "GET request failed. No connection could be established to the "
261 "MemoryX-REST server at host="
262 << host_ << ", port=" << port_;
263 }
264
265 return item_keys;
266 }
267
268 std::vector<std::string>
269 RestPersistence::getRestContainers(const armarx::armem::MemoryID& id)
270 {
271 std::string path = buildPath(id);
272 std::string query = "containers";
273 std::string url = path + "?" + query;
274
275 ARMARX_DEBUG << "GET request: Get containers from MemoryX-REST server: url=" << url;
276
277 auto res = client_->Get(url);
278
279 std::vector<std::string> item_keys;
280
281 if (res && res->status == httplib::StatusCode::OK_200)
282 {
283 ARMARX_DEBUG << "GET request response: " << res->body;
284
285 try
286 {
287 nlohmann::json json_response = nlohmann::json::parse(res->body);
288
289 if (json_response.contains("keys") && json_response["keys"].is_array())
290 {
291 item_keys = json_response["keys"].get<std::vector<std::string>>();
292 }
293 }
294 catch (const std::exception& e)
295 {
296 ARMARX_ERROR << "GET request: Error parsing JSON: " << e.what();
297 }
298 }
299 else if (res)
300 {
301 ARMARX_DEBUG << "GET request failed. status=" << res->status << ", url=" << url;
302 }
303 else
304 {
305 ARMARX_DEBUG << "GET request failed. No connection could be established to the "
306 "MemoryX-REST server at host="
307 << host_ << ", port=" << port_;
308 }
309
310 return item_keys;
311 }
312
313 std::vector<unsigned char>
314 RestPersistence::readItemFromRest(const armarx::armem::MemoryID& id, std::string& key)
315 {
316 std::string path = buildPath(id);
317 std::string query = "item=" + key;
318 std::string url = path + "?" + query;
319
320 ARMARX_DEBUG << "GET request: Read data from MemoryX-REST server: key=" << key
321 << ", url=" << url;
322
323 auto res = client_->Get(url);
324
325 std::vector<unsigned char> data;
326
327 if (res && res->status == httplib::StatusCode::OK_200)
328 {
329 ARMARX_DEBUG << "GET request response: " << res->body;
330
331 data = std::vector<unsigned char>(res->body.begin(), res->body.end());
332 }
333 else if (res && res->status == httplib::StatusCode::NotFound_404)
334 {
335 ARMARX_DEBUG << "GET request failed: REST-LTM does not contain any item with key="
336 << key;
337 }
338 else if (res)
339 {
340 ARMARX_DEBUG << "GET request failed. status=" << res->status << ", key=" << key
341 << ", url=" << url;
342 }
343 else
344 {
345 ARMARX_DEBUG << "GET request failed. No connection could be established to the "
346 "MemoryX-REST server at host="
347 << host_ << ", port=" << port_;
348 }
349
350 return data;
351 }
352
353 void
354 RestPersistence::writeItemToRest(const armarx::armem::MemoryID& id,
355 std::string& key,
356 const std::vector<unsigned char>& data)
357 {
358 std::string path = buildPath(id);
359 std::string query = "item=" + key;
360 std::string url = path + "?" + query;
361
362 ARMARX_DEBUG << "PUT request: Write data to MemoryX-REST server: key=" << key
363 << ", url=" << url;
364
365 std::string body(data.begin(), data.end());
366
367 auto res = client_->Put(url, body, "application/json");
368
369 if (res && res->status == httplib::StatusCode::OK_200)
370 {
371 ARMARX_DEBUG << "PUT request response: " << res->body;
372 }
373 else if (res)
374 {
375 ARMARX_DEBUG << "PUT request failed. status=" << res->status << ", key=" << key
376 << ", url=" << url;
377 }
378 else
379 {
380 ARMARX_DEBUG << "PUT request failed. No connection could be established to the "
381 "MemoryX-REST server at host="
382 << host_ << ", port=" << port_;
383 }
384 }
385
386 void
387 RestPersistence::writeItemToRest(const armarx::armem::MemoryID& id,
388 std::string& key,
389 nlohmann::json& jsonData)
390 {
391 std::string str_data = jsonData.dump();
392 std::vector<unsigned char> data(str_data.begin(), str_data.end());
393
394 writeItemToRest(id, key, DataType::JSON, data);
395 }
396
397 void
398 RestPersistence::writeItemToRest(const armarx::armem::MemoryID& id,
399 std::string& key,
400 DataType type,
401 const std::vector<unsigned char>& data)
402 {
403 std::string path = buildPath(id);
404 std::string mime_type = getMimeType(type);
405 std::string query = "?item=" + key;
406
407 std::string body(data.begin(), data.end());
408
409 auto res = client_->Put(path + query, body, mime_type);
410
411 if (res)
412 {
413 ARMARX_DEBUG << "Status: " << res->status;
414 ARMARX_DEBUG << "Response: " << res->body;
415 }
416 else
417 {
418 ARMARX_DEBUG << "Request failed. Error: " << res.error();
419 }
420 }
421
422 void
423 RestPersistence::removeRestItem(const armarx::armem::MemoryID& id, std::string& key)
424 {
425 std::string path = buildPath(id);
426 std::string query = "item=" + key;
427 std::string url = path + "?" + query;
428
429 ARMARX_DEBUG << "DELETE request: Remove item from MemoryX-REST server: key=" << key
430 << ", url=" << url;
431
432
433 auto res = client_->Delete(url);
434
435 if (res && res->status == httplib::StatusCode::OK_200)
436 {
437 ARMARX_DEBUG << "DELETE request successful: " << res->body;
438 }
439 else if (res && res->status == httplib::StatusCode::NotFound_404)
440 {
441 ARMARX_DEBUG << "DELETE request failed. REST-LTM does not contain any item with key="
442 << key;
443 }
444 else if (res)
445 {
446 ARMARX_DEBUG << "DELETE request failed. Status: " << res->status;
447 }
448 else
449 {
450 ARMARX_DEBUG << "DELETE request failed. No connection could be established to the "
451 "MemoryX-REST server at host="
452 << host_ << ", port=" << port_;
453 }
454 }
455
456 void
457 RestPersistence::setPort(int port)
458 {
459 port_ = port;
460 resetClient();
461 }
462
463 int
464 RestPersistence::getPort() const
465 {
466 return port_;
467 }
468
469 void
470 RestPersistence::setHost(std::string& host)
471 {
472 host_ = host;
473 resetClient();
474 }
475
476 std::string
477 RestPersistence::getHost()
478 {
479 return host_;
480 }
481
482 std::string
483 RestPersistence::buildPath(const armarx::armem::MemoryID& id)
484 {
485 std::string url = "/ltm/" + getExportName();
486
487 if (id.hasMemoryName())
488 {
490 }
491 if (id.hasCoreSegmentName())
492 {
493 url +=
495 }
496 if (id.hasProviderSegmentName())
497 {
499 id.providerSegmentName);
500 }
501 if (id.hasEntityName())
502 {
504 }
505 if (id.hasTimestamp())
506 {
507 url += "/" + id.timestampStr();
508 }
509 if (id.hasInstanceIndex())
510 {
511 url += "/" + id.instanceIndexStr();
512 }
513
514 return url;
515 }
516
517 std::string
518 RestPersistence::getMimeType(DataType type)
519 {
520
521 std::string mime_type;
522
523 if (type == DataType::JSON)
524 {
525 mime_type = "application/json";
526 }
527 else if (type == DataType::PNG)
528 {
529 mime_type = "image/png";
530 }
531
532 return mime_type;
533 }
534
535} // namespace armarx::armem::server::ltm::persistence
uint8_t data[1]
bool enabled_
If false, the strategy is not writing or reading anything.
bool containsContainer(const armarx::armem::MemoryID &id, std::string key) override
std::vector< std::string > getItemKeys(const armarx::armem::MemoryID &id) override
Keys of the actual items containing data stored for the memory id.
void storeItem(const armarx::armem::MemoryID &id, std::string key, std::vector< unsigned char > &data) override
Stores an item containing actual data for the current memory id.
bool containsItem(const armarx::armem::MemoryID &id, std::string key) override
std::vector< std::string > getContainerKeys(const armarx::armem::MemoryID &id) override
Returns keys that allow use to move a step further in the hierarchy (e.g.
std::vector< unsigned char > retrieveItem(const armarx::armem::MemoryID &id, std::string key) override
Retrieve the actual data of an item stored for the memory id.
void createPropertyDefinitions(PropertyDefinitionsPtr &defs, const std::string &prefix) override
#define ARMARX_IMPORTANT
The logging level for always important information, but expected behaviour (in contrast to ARMARX_WAR...
Definition Logging.h:190
#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
std::string escapeName(const std::string &segmentName)
IceUtil::Handle< class PropertyDefinitionContainer > PropertyDefinitionsPtr
PropertyDefinitions smart pointer type.
@ OK_200
Definition httplib.h:439
@ NotFound_404
Definition httplib.h:466