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 {
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)
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());
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());
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)
321 << std::string(constantes::INSTANCES);
322 auto array_builder = bsoncxx::builder::basic::array{};
323
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 =
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
constexpr T c
MemoryID getEntitySnapshotID() const
Definition MemoryID.cpp:318
std::string coreSegmentName
Definition MemoryID.h:51
std::string str(bool escapeDelimiters=true) const
Get a string representation of this memory ID.
Definition MemoryID.cpp:102
std::string entityName
Definition MemoryID.h:53
std::string memoryName
Definition MemoryID.h:50
MemoryID withInstanceIndex(int index) const
Definition MemoryID.cpp:441
std::string providerSegmentName
Definition MemoryID.h:52
MemoryID getEntityID() const
Definition MemoryID.cpp:310
EntitySnapshotT & addSnapshot(const Time &timestamp)
Add a snapshot at the given time.
Definition EntityBase.h:673
bool forEachSnapshot(SnapshotFunctionT &&func)
Definition EntityBase.h:391
bool forEachCoreSegment(CoreSegmentFunctionT &&func)
Definition MemoryBase.h:188
bool hasCoreSegment(const std::string &name) const
Definition MemoryBase.h:107
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:261
bool hasEntity(const std::string &name) const
EntityT & addEntity(const std::string &name)
Add an empty entity with the given name.
Base class for all exceptions thrown by the armem library.
Definition ArMemError.h:19
Indicates that a memory ID is invalid, e.g.
Definition ArMemError.h:152
Client-side working memory core segment.
Client-side working memory entity snapshot.
Client-side working memory entity.
Client-side working memory.
Client-side working memory provider segment.
static data::DictPtr ConvertFromNlohmannJSONObject(const nlohmann::json &, const armarx::aron::Path &p={})
static nlohmann::json ConvertToNlohmannJSON(const data::VariantPtr &)
static DateTime microSeconds(long microSeconds)
Definition DateTime.h:94
std::int64_t toMicroSeconds() const
Definition DateTime.h:101
#define q
void store(const mongocxx::database &db, const armem::wm::Memory &m)
void load(const mongocxx::database &db, armem::wm::Memory &m)
void convert(const mongocxx::database &db, armem::wm::Memory &m)
armem::wm::EntityInstance EntityInstance
void from_aron(const aron::data::DictPtr &metadata, const aron::data::DictPtr &data, wm::EntityInstance &)
convert from metadata and data aron instance
void to_aron(aron::data::DictPtr &metadata, aron::data::DictPtr &data, const wm::EntityInstance &)
convert to metadata and aron instance
auto & getInstance(const MemoryID &instanceID)
Retrieve an entity instance.