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