operations.cpp
Go to the documentation of this file.
1 #include "operations.h"
2 
3 // Simox
4 #include <SimoxUtility/json.h>
5 
8 
9 #include "../operations.h"
10 
12 {
13  namespace bsoncxxbuilder = bsoncxx::builder::stream;
14  namespace bsoncxxdoc = bsoncxx::document;
15 
16  namespace
17  {
18  void
19  mongodbInsertForeignKey(mongocxx::collection& coll, const std::string& key)
20  {
21  auto q = bsoncxxbuilder::document{} << std::string(constantes::FOREIGN_KEY) << key
22  << bsoncxxbuilder::finalize;
23  coll.insert_one(q.view());
24  }
25 
26  bool
27  mongodbContainsForeignKey(mongocxx::collection& coll, const std::string& key)
28  {
29  // check mongodb
30  auto q = bsoncxxbuilder::document{} << std::string(constantes::FOREIGN_KEY) << key
31  << bsoncxxbuilder::finalize;
32  auto res = coll.find_one(q.view());
33  return (bool)res;
34  }
35 
36  bool
37  mongodbContainsTimestamp(mongocxx::collection& coll, const long ts)
38  {
39  // check mongodb
40  auto q = bsoncxxbuilder::document{} << std::string(constantes::TIMESTAMP) << ts
41  << bsoncxxbuilder::finalize;
42  auto res = coll.find_one(q.view());
43  return (bool)res;
44  }
45  } // namespace
46 
47  void
48  load(const mongocxx::database& db, armem::wm::Memory& m)
49  {
50  if (!db.has_collection(m.id().str()))
51  {
52  return;
53  }
54  mongocxx::collection coll = db.collection(m.id().str());
55  mongocxx::cursor cursor = coll.find({});
56  for (const auto& doc : cursor)
57  {
58  auto el = doc[constantes::FOREIGN_KEY];
59  auto foreignKey = el.get_utf8().value;
60 
61  MemoryID i((std::string)foreignKey);
62  if (i.memoryName != m.id().memoryName)
63  {
65  i,
66  "A MemoryID in mongodb was invalid. Found the wrong memory name: " + i.str());
67  }
68 
69  std::string k = i.coreSegmentName;
70  if (m.hasCoreSegment(k))
71  {
72  throw error::ArMemError("Somehow the container already contains the key k = " + k +
73  ". Do you have double entries in mongodb?");
74  }
75  else
76  {
77  auto& cSeg = m.addCoreSegment(k);
78  load(db, cSeg);
79  }
80  }
81  }
82 
83  void
84  load(const mongocxx::database& db, armem::wm::CoreSegment& c)
85  {
86  if (!db.has_collection(c.id().str()))
87  {
88  return;
89  }
90  mongocxx::collection coll = db.collection(c.id().str());
91  mongocxx::cursor cursor = coll.find({});
92  for (const auto& doc : cursor)
93  {
94  auto el = doc[constantes::FOREIGN_KEY];
95  auto foreignKey = el.get_utf8().value;
96 
97  MemoryID i((std::string)foreignKey);
98  if (i.coreSegmentName != c.id().coreSegmentName || i.memoryName != c.id().memoryName)
99  {
101  i,
102  "A MemoryID in mongodb was invalid. Found the wrong memory name: " + i.str());
103  }
104 
105  std::string k = i.providerSegmentName;
106  if (c.hasProviderSegment(k))
107  {
108  throw error::ArMemError("Somehow the container already contains the key k = " + k +
109  ". Do you have double entries in mongodb?");
110  }
111  else
112  {
113  auto& pSeg = c.addProviderSegment(k);
114  load(db, pSeg);
115  }
116  }
117  }
118 
119  void
120  load(const mongocxx::database& db, armem::wm::ProviderSegment& p)
121  {
122  if (!db.has_collection(p.id().str()))
123  {
124  return;
125  }
126  mongocxx::collection coll = db.collection(p.id().str());
127  mongocxx::cursor cursor = coll.find({});
128  for (const auto& doc : cursor)
129  {
130  auto el = doc[constantes::FOREIGN_KEY];
131  auto foreignKey = el.get_utf8().value;
132 
133  MemoryID i((std::string)foreignKey);
136  {
138  i,
139  "A MemoryID in mongodb was invalid. Found the wrong memory name: " + i.str());
140  }
141 
142  std::string k = i.entityName;
143  if (p.hasEntity(k))
144  {
145  throw error::ArMemError("Somehow the container already contains the key k = " + k +
146  ". Do you have double entries in mongodb?");
147  }
148  else
149  {
150  auto& eSeg = p.addEntity(k);
151  load(db, eSeg);
152  }
153  }
154  }
155 
156  void
157  load(const mongocxx::database& db, armem::wm::Entity& e)
158  {
159  if (!db.has_collection(e.id().str()))
160  {
161  return;
162  }
163  mongocxx::collection coll = db.collection(e.id().str());
164  mongocxx::cursor cursor = coll.find({});
165  for (const auto& doc : cursor)
166  {
167  auto ts = armem::Time::microSeconds(doc[constantes::TIMESTAMP].get_int64().value);
168  auto& newSnapshot = e.addSnapshot(ts);
169 
170  auto i = doc[constantes::INSTANCES];
171  unsigned long length =
172  std::distance(i.get_array().value.begin(), i.get_array().value.end());
173 
174  for (unsigned long i = 0; i < length; ++i)
175  {
176  // add an empty instance as reference
177  newSnapshot.addInstance({});
178  }
179 
180  // check to update lastSnapshot map TODO
181  //checkUpdateLatestSnapshot(newSnapshot);
182  }
183  }
184 
185  void
186  convert(const mongocxx::database& db, armem::wm::Memory& m)
187  {
188  m.forEachCoreSegment([&db](armem::wm::CoreSegment& e) { convert(db, e); });
189  }
190 
191  void
192  convert(const mongocxx::database& db, armem::wm::CoreSegment& c)
193  {
194  c.forEachProviderSegment([&db](armem::wm::ProviderSegment& e) { convert(db, e); });
195  }
196 
197  void
198  convert(const mongocxx::database& db, armem::wm::ProviderSegment& p)
199  {
200  p.forEachEntity([&db](armem::wm::Entity& e) { convert(db, e); });
201  }
202 
203  void
204  convert(const mongocxx::database& db, armem::wm::Entity& e)
205  {
206  e.forEachSnapshot(
207  [&db](armem::wm::EntitySnapshot& e)
208  {
209  if (!ltm::util::entityHasData(e))
210  {
211  // Get data from mongodb
212  auto eColl = db.collection(e.id().getEntityID().str());
213  auto q = bsoncxxbuilder::document{} << std::string(constantes::TIMESTAMP)
214  << e.id().timestamp.toMicroSeconds()
215  << bsoncxxbuilder::finalize;
216  auto res = eColl.find_one(q.view());
217 
218  if (!res)
219  {
220  // break if the data could not be found in ltm storage
221  // perhaps its a not-set maybe type from the cache (not yet consollidated to ltm)
222  return false;
223  }
224 
225  // convert full json of this entry
226  nlohmann::json json = nlohmann::json::parse(bsoncxx::to_json(*res));
227  nlohmann::json instances = json[constantes::INSTANCES];
228 
229  if (instances.size() != e.size())
230  {
231  throw error::ArMemError(
232  "The size of the mongodb entity entry at id " +
233  e.id().getEntitySnapshotID().str() +
234  " has wrong size. Expected: " + std::to_string(e.size()) +
235  " but got: " + std::to_string(instances.size()));
236  }
237 
238  for (unsigned int i = 0; i < e.size(); ++i)
239  {
240  auto& ins = e.getInstance(e.id().withInstanceIndex(i));
241 
242  // get ionstance json
243  nlohmann::json doc = instances[i];
246 
247  // remove metadata
249  from_aron(aron, tmp);
250 
251  // set data
252  ins.data() = tmp.data();
253  }
254  }
255  return true;
256  });
257  }
258 
259  void
260  store(const mongocxx::database& db, const armem::wm::Memory& m)
261  {
262  auto coll = db.collection(m.id().str());
264  [&db, &coll](armem::wm::CoreSegment& e)
265  {
266  if (!mongodbContainsForeignKey(coll, e.id().str()))
267  {
268  mongodbInsertForeignKey(coll, e.id().str());
269  }
270 
271  store(db, e);
272  });
273  }
274 
275  void
276  store(const mongocxx::database& db, const armem::wm::CoreSegment& c)
277  {
278  auto coll = db.collection(c.id().str());
279  c.forEachProviderSegment(
280  [&db, &coll](armem::wm::ProviderSegment& e)
281  {
282  if (!mongodbContainsForeignKey(coll, e.id().str()))
283  {
284  mongodbInsertForeignKey(coll, e.id().str());
285  }
286 
287  store(db, e);
288  });
289  }
290 
291  void
292  store(const mongocxx::database& db, const armem::wm::ProviderSegment& p)
293  {
294  auto coll = db.collection(p.id().str());
295  p.forEachEntity(
296  [&db, &coll](armem::wm::Entity& e)
297  {
298  if (!mongodbContainsForeignKey(coll, e.id().str()))
299  {
300  mongodbInsertForeignKey(coll, e.id().str());
301  }
302 
303  store(db, e);
304  });
305  }
306 
307  void
308  store(const mongocxx::database& db, const armem::wm::Entity& e)
309  {
310  auto coll = db.collection(e.id().str());
311  e.forEachSnapshot(
312  [&coll](armem::wm::EntitySnapshot& e)
313  {
314  if (!mongodbContainsTimestamp(coll, e.id().timestamp.toMilliSeconds()))
315  {
316  // timestamp not found in mongodb ==> new entry
317  bsoncxxbuilder::document builder{};
318  auto in_array = builder << std::string(constantes::ID) << e.id().str()
319  << std::string(constantes::TIMESTAMP)
320  << e.id().timestamp.toMicroSeconds()
321  << std::string(constantes::INSTANCES);
322  auto array_builder = bsoncxx::builder::basic::array{};
323 
324  e.forEachInstance(
325  [&array_builder](const wm::EntityInstance& e)
326  {
327  auto aron = std::make_shared<aron::data::Dict>();
328  to_aron(aron, e);
329  nlohmann::json j =
330  aron::converter::AronNlohmannJSONConverter::ConvertToNlohmannJSON(
331  aron);
332 
333  auto doc_value = bsoncxx::from_json(j.dump(2));
334  array_builder.append(doc_value);
335  });
336 
337  auto after_array = in_array << array_builder;
338  bsoncxx::document::value doc = after_array
339  << bsoncxx::builder::stream::finalize;
340  coll.insert_one(doc.view());
341 
342  // check to update lastSnapshot map TODO
343  //checkUpdateLatestSnapshot(e);
344  }
345  });
346  }
347 
348 } // namespace armarx::armem::server::ltm::mongodb::util
armarx::armem::MemoryID::timestamp
Time timestamp
Definition: MemoryID.h:54
armarx::armem::base::EntitySnapshotBase::getInstance
EntityInstanceT & getInstance(int index)
Get the given instance.
Definition: EntitySnapshotBase.h:114
operations.h
armarx::armem::wm::ProviderSegment
Client-side working memory provider segment.
Definition: memory_definitions.h:105
armarx::armem::MemoryID::providerSegmentName
std::string providerSegmentName
Definition: MemoryID.h:52
armarx::armem::server::ltm::mongodb::constantes::FOREIGN_KEY
const std::string FOREIGN_KEY
Definition: operations.h:14
armarx::armem::wm::EntityInstance
Client-side working entity instance.
Definition: memory_definitions.h:32
armarx::armem::base::EntitySnapshotBase::forEachInstance
bool forEachInstance(InstanceFunctionT &&func)
Definition: EntitySnapshotBase.h:178
armarx::armem::server::ltm::mongodb::util::convert
void convert(const mongocxx::database &db, armem::wm::Memory &m)
Definition: operations.cpp:186
armarx::armem::MemoryID::str
std::string str(bool escapeDelimiters=true) const
Get a string representation of this memory ID.
Definition: MemoryID.cpp:102
armarx::aron::data::converter::AronNlohmannJSONConverter::ConvertFromNlohmannJSONObject
static data::DictPtr ConvertFromNlohmannJSONObject(const nlohmann::json &, const armarx::aron::Path &p={})
Definition: NLohmannJSONConverter.cpp:25
armarx::armem::error::ArMemError
Base class for all exceptions thrown by the armem library.
Definition: ArMemError.h:18
c
constexpr T c
Definition: UnscentedKalmanFilterTest.cpp:46
aron_conversions.h
armarx::armem::MemoryID::coreSegmentName
std::string coreSegmentName
Definition: MemoryID.h:51
armarx::armem::base::EntityBase::addSnapshot
EntitySnapshotT & addSnapshot(const Time &timestamp)
Add a snapshot at the given time.
Definition: EntityBase.h:629
NLohmannJSONConverter.h
armarx::armem::base::detail::MemoryContainerBase::size
std::size_t size() const
Definition: MemoryContainerBase.h:47
armarx::armem::base::MemoryBase::forEachCoreSegment
bool forEachCoreSegment(CoreSegmentFunctionT &&func)
Definition: MemoryBase.h:186
armarx::armem::base::MemoryBase::hasCoreSegment
bool hasCoreSegment(const std::string &name) const
Definition: MemoryBase.h:105
armarx::armem::server::ltm::mongodb::util::store
void store(const mongocxx::database &db, const armem::wm::Memory &m)
Definition: operations.cpp:260
cxxopts::value
std::shared_ptr< Value > value()
Definition: cxxopts.hpp:855
armarx::armem::MemoryID
A memory ID.
Definition: MemoryID.h:47
if
if(!yyvaluep)
Definition: Grammar.cpp:645
armarx::core::time::DateTime::toMicroSeconds
std::int64_t toMicroSeconds() const
Definition: DateTime.h:101
armarx::armem::base::ProviderSegmentBase::hasEntity
bool hasEntity(const std::string &name) const
Definition: ProviderSegmentBase.h:108
armarx::armem::wm::CoreSegment
Client-side working memory core segment.
Definition: memory_definitions.h:119
armarx::armem::MemoryID::getEntitySnapshotID
MemoryID getEntitySnapshotID() const
Definition: MemoryID.cpp:318
armarx::armem::wm::Memory
Client-side working memory.
Definition: memory_definitions.h:133
armarx::armem::server::ltm::mongodb::constantes::TIMESTAMP
const std::string TIMESTAMP
Definition: operations.h:16
armarx::armem::base::MemoryBase::addCoreSegment
CoreSegmentT & addCoreSegment(const std::string &name, aron::type::ObjectPtr coreSegmentType=nullptr, const std::vector< PredictionEngine > &predictionEngines={})
Add an empty core segment with the given name, type and prediction engines.
Definition: MemoryBase.h:259
armarx::armem::wm::EntitySnapshot
Client-side working memory entity snapshot.
Definition: memory_definitions.h:80
armarx::armem::base::detail::MemoryItem::id
MemoryID & id()
Definition: MemoryItem.h:25
q
#define q
armarx::to_string
const std::string & to_string(const std::string &s)
Definition: StringHelpers.h:41
armarx::armem::MemoryID::entityName
std::string entityName
Definition: MemoryID.h:53
armarx::armem::MemoryID::memoryName
std::string memoryName
Definition: MemoryID.h:50
armarx::data::to_json
void to_json(nlohmann::json &j, const PackagePath &pp)
Definition: json_conversions.h:36
armarx::armem::server::ltm::mongodb::util
Definition: operations.cpp:11
armarx::armem::MemoryID::getEntityID
MemoryID getEntityID() const
Definition: MemoryID.cpp:310
armarx::armem::from_aron
void from_aron(const aron::data::DictPtr &metadata, const aron::data::DictPtr &data, wm::EntityInstance &)
convert from metadata and data aron instance
Definition: aron_conversions.cpp:15
armarx::armem::error::InvalidMemoryID
Indicates that a memory ID is invalid, e.g.
Definition: ArMemError.h:151
armarx::armem::server::ltm::mongodb::constantes::ID
const std::string ID
Definition: operations.h:15
armarx::armem::base::ProviderSegmentBase::forEachEntity
bool forEachEntity(EntityFunctionT &&func)
Definition: ProviderSegmentBase.h:189
distance
double distance(const Point &a, const Point &b)
Definition: point.hpp:95
armarx::core::time::DateTime::microSeconds
static DateTime microSeconds(long microSeconds)
Definition: DateTime.h:94
armarx::armem::base::EntityBase::forEachSnapshot
bool forEachSnapshot(SnapshotFunctionT &&func)
Definition: EntityBase.h:390
armarx::armem::MemoryID::withInstanceIndex
MemoryID withInstanceIndex(int index) const
Definition: MemoryID.cpp:441
armarx::armem::wm::Entity
Client-side working memory entity.
Definition: memory_definitions.h:93
armarx::armem::base::ProviderSegmentBase::addEntity
EntityT & addEntity(const std::string &name)
Add an empty entity with the given name.
Definition: ProviderSegmentBase.h:298
armarx::armem::server::ltm::mongodb::constantes::INSTANCES
const std::string INSTANCES
Definition: operations.h:17
armarx::armem::base::EntityInstanceBase::data
const DataT & data() const
Definition: EntityInstanceBase.h:129
armarx::armem::server::ltm::mongodb::util::load
void load(const mongocxx::database &db, armem::wm::Memory &m)
Definition: operations.cpp:48