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