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
RestPersistence.h
armarx::armem::server::ltm::persistence::DataType
DataType
Definition: RestPersistence.h:11
httplib::NotFound_404
@ NotFound_404
Definition: httplib.h:466
ARMARX_IMPORTANT
#define ARMARX_IMPORTANT
Definition: Logging.h:190
armarx::armem::server::ltm::persistence::RestPersistence::getItemKeys
std::vector< std::string > getItemKeys(const armarx::armem::MemoryID &id) override
Keys of the actual items containing data stored for the memory id.
Definition: RestPersistence.cpp:24
armarx::armem::server::ltm::persistence::RestPersistence::containsItem
bool containsItem(const armarx::armem::MemoryID &id, std::string key) override
Definition: RestPersistence.cpp:50
armarx::armem::server::ltm::persistence::MemoryPersistenceStrategy::enabled_
bool enabled_
If false, the strategy is not writing or reading anything.
Definition: MemoryPersistenceStrategy.h:213
armarx::armem::server::ltm ::util::fs::detail::escapeName
std::string escapeName(const std::string &segmentName)
Definition: filesystem.cpp:19
armarx::armem::server::ltm::persistence::RestPersistence::retrieveItem
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.
Definition: RestPersistence.cpp:78
armarx::armem::server::ltm::persistence
Definition: DiskPersistence.cpp:5
armarx::armem::server::ltm::persistence::RestPersistence::DEFAULT_HOST
const static std::string DEFAULT_HOST
Definition: RestPersistence.h:88
armarx::armem::server::ltm::persistence::RestPersistence::containsContainer
bool containsContainer(const armarx::armem::MemoryID &id, std::string key) override
Definition: RestPersistence.cpp:37
httplib::OK_200
@ OK_200
Definition: httplib.h:439
armarx::armem::server::ltm::detail::mixin::JSON
@ JSON
Definition: RESTStorageMixin.h:20
armarx::armem::MemoryID
A memory ID.
Definition: MemoryID.h:47
armarx::armem::server::ltm::persistence::RestPersistence::checkConnection
bool checkConnection()
Checks if the server is up.
Definition: RestPersistence.cpp:104
data
uint8_t data[1]
Definition: EtherCATFrame.h:68
ARMARX_DEBUG
#define ARMARX_DEBUG
Definition: Logging.h:184
armarx::armem::server::ltm::persistence::RestPersistence::getContainerKeys
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.
Definition: RestPersistence.cpp:11
ARMARX_ERROR
#define ARMARX_ERROR
Definition: Logging.h:196
armarx::armem::server::ltm::persistence::MemoryPersistenceStrategy::getExportName
std::string getExportName()
Definition: MemoryPersistenceStrategy.h:150
armarx::armem::server::ltm::persistence::RestPersistence::createPropertyDefinitions
void createPropertyDefinitions(PropertyDefinitionsPtr &defs, const std::string &prefix) override
Definition: RestPersistence.cpp:96
armarx::armem::server::ltm::persistence::RestPersistence::storeItem
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.
Definition: RestPersistence.cpp:63
armarx::armem::server::ltm::persistence::MemoryPersistenceStrategy::identifier_
std::string identifier_
Name of the strategy.
Definition: MemoryPersistenceStrategy.h:201
armarx::armem::laser_scans::constants::memoryName
const std::string memoryName
Definition: constants.h:28
IceUtil::Handle< class PropertyDefinitionContainer >
armarx::armem::server::ltm::detail::mixin::PNG
@ PNG
Definition: RESTStorageMixin.h:20
filesystem.h