EntityInstance.cpp
Go to the documentation of this file.
1// Header
2#include "EntityInstance.h"
3
4// STD / STL
5#include <SimoxUtility/algorithm/string/string_tools.h>
6
7// ArmarX
10
13
15{
16 EntityInstance::EntityInstance(const std::string& exportName,
17 const armem::MemoryID& id /* UNESCAPED */,
18 const std::shared_ptr<Processors>& filters,
19 const std::shared_ptr<persistence::MemoryPersistenceStrategy>& persistenceStrategy) :
20 EntityInstanceBase(exportName, id, filters),
21 persistenceStrategy_(persistenceStrategy)
22 {
23 //start();
24 }
25
26 void
28 {
30
31 int index = std::stoi(getMemoryID().getEntityInstanceID().getLeafItem());
32
33 armem::wm::EntityInstance wmEntityInstance = armem::wm::EntityInstance(index, wmEntitySnapshot.id());
34
35 // add instance. Do not set data, since we only return references
36 wmEntitySnapshot.addInstance(wmEntityInstance);
37 }
38
39 void
41 {
43
44 ARMARX_DEBUG << "Resolve entity instance id=" << id().cleanID().str();
45
46 std::string origin = "undefined3";
47
48 auto& dictConverter = processors->defaultObjectConverter;
49
50
51 aron::data::DictPtr datadict = nullptr;
52 aron::data::DictPtr metadatadict = nullptr;
53
54
55 std::string dataFilename = (persistence::MemoryPersistenceStrategy::DATA_FILENAME + dictConverter.suffix);
56 std::string metadataFilename = (persistence::MemoryPersistenceStrategy::METADATA_FILENAME + dictConverter.suffix);
57
58 if (persistenceStrategy_->containsItem(id(), dataFilename))
59 {
60 auto datafilecontent = persistenceStrategy_->retrieveItem(id(), dataFilename);
61
62 try
63 {
64 auto dataaron = dictConverter.convert({datafilecontent, ""}, {});
65 datadict = aron::data::Dict::DynamicCastAndCheck(dataaron);
66 }
67 catch (std::exception& ex)
68 {
69 ARMARX_ERROR << "Exception during conversion from file into json object. At entity instance=" << id().cleanID().str() << ", file=" << dataFilename << ", error message=" << ex.what();
70 return;
71 }
72 }
73 else
74 {
75 // Not "continuing": the loop below dereferences datadict, and from_aron() would be
76 // handed a null data dict. A half-written export -- the LTM drops or fails writes
77 // without telling the caller -- used to segfault the server on load.
78 ARMARX_WARNING << "Could not find the data file '" << dataFilename
79 << "' for entity instance=" << id().cleanID().str()
80 << ". Skipping this instance.";
81 return;
82 }
83
84 if (persistenceStrategy_->containsItem(id(), metadataFilename))
85 {
86 auto itemResult = persistenceStrategy_->retrieveItemWithOrigin(id(), metadataFilename);
87 auto metadatafilecontent = itemResult.data;
88 origin = itemResult.origin;
89
90 try
91 {
92 auto metadataaron = dictConverter.convert({metadatafilecontent, ""}, {});
93 metadatadict = aron::data::Dict::DynamicCastAndCheck(metadataaron);
94 }
95 catch (std::exception& ex)
96 {
97 ARMARX_ERROR << "Exception during conversion from file into json object. At entity instance=" << id().cleanID().str() << ", file=" << metadataFilename << ", error message=" << ex.what();
98 return;
99 }
100 }
101 else
102 {
103 // Likewise not "continuing": every field from_aron() reads -- referencedTime, sentTime,
104 // arrivedTime, confidence -- lives in the metadata, and it opens with
105 // ARMARX_CHECK_NOT_NULL(metadata), so this threw from deep inside instead.
106 ARMARX_WARNING << "Could not find the metadata file '" << metadataFilename
107 << "' for entity instance=" << id().cleanID().str()
108 << ". Skipping this instance.";
109 return;
110 }
111
112 for (const auto& [key, m] : datadict->getElements())
113 {
114 for (auto& f : processors->converters)
115 {
116 // iterate over all files and search for matching ones.
117 // We cannot simply check for the existence of a file because we do not know the
118 // mode (filename = memberName.mode.suffix)
119 for (const auto& entityInstanceKey : persistenceStrategy_->getItemKeys(id()))
120 {
121 if (simox::alg::starts_with(entityInstanceKey, key) and
122 simox::alg::ends_with(entityInstanceKey, f->suffix))
123 {
124 std::string mode = simox::alg::remove_suffix(
125 simox::alg::remove_prefix(entityInstanceKey, key), f->suffix);
126
127 auto memberfilecontent = persistenceStrategy_->retrieveItem(id(), entityInstanceKey);
128 auto memberaron = f->convert(
129 {memberfilecontent, mode},
130 armarx::aron::Path(datadict->getPath(), std::vector<std::string>{key}));
131 datadict->setElement(key, memberaron);
132 break;
133 }
134 }
135 }
136 }
137
138 from_aron(metadatadict, datadict, wmEntityInstance);
139
140 // TODO: as parameter
141 bool usePersistenceStrategyAsOrigin = true;
142
143 if (usePersistenceStrategyAsOrigin)
144 {
145 wmEntityInstance.metadata().origin = origin;
146 }
147 }
148
149 nlohmann::json
151 {
153
154 if (id().instanceIndex < 0)
155 {
157 << "During storage of segment '" << wmEntitySnapshot.id().str()
158 << "' I noticed that the corresponding LTM has no id set. "
159 << "I set the id of the LTM to the same name, however this should not happen!";
160 id().timestamp = wmEntitySnapshot.id().timestamp;
161 }
162
163 auto& dictConverter = processors->defaultObjectConverter;
164
165 ARMARX_DEBUG << "Storing entity instance id=" << id().cleanID().str();
166
167 // data
168 auto dataAron = std::make_shared<aron::data::Dict>();
169 auto metadataAron = std::make_shared<aron::data::Dict>();
170 to_aron(metadataAron, dataAron, wmEntitySnapshot);
171
172 std::shared_ptr<aron::data::Dict> source;
173
174 bool saveAndExtract =
175 false; //if true the data is saved in extracted form and in data.aron.json
176 // this is needed if several LTMs are recorded at once because otherwise the data from the data.aron.json
177 // is not there anymore to extract from
178
179 if (saveAndExtract)
180 {
181 source = dataAron->clone();
182 }
183 else
184 {
185 source = dataAron;
186 }
187
188 // check special members for special converters
189 for (auto& converter : processors->converters)
190 {
191 ARMARX_CHECK_NOT_NULL(converter);
192 ARMARX_CHECK_NOT_NULL(converter->extractor);
193 auto dataExt = converter->extractor->extract(source);
194
195 for (const auto& [memberName, var] : dataExt.extraction)
196 {
198
199 auto [memberDataVec, memberDataModeSuffix] = converter->convert(var);
200
201 std::string filename = (memberName + memberDataModeSuffix + converter->suffix);
202
203 persistenceStrategy_->storeItem(id(), filename, memberDataVec);
204 }
205 }
206
207 // convert dict and metadata
208 auto [dataVec, dataVecModeSuffix] = dictConverter.convert(dataAron);
209 auto [metadataVec, metadataVecModeSuffix] = dictConverter.convert(metadataAron);
210 ARMARX_CHECK_EMPTY(dataVecModeSuffix);
211 ARMARX_CHECK_EMPTY(metadataVecModeSuffix);
212
213 auto dataToReturn = nlohmann::json::parse(std::string(dataVec.begin(), dataVec.end()));
214
215 {
216 std::string dataFilename = (persistence::MemoryPersistenceStrategy::DATA_FILENAME + dictConverter.suffix);
217 std::string metadataFilename = (persistence::MemoryPersistenceStrategy::METADATA_FILENAME + dictConverter.suffix);
218
219 persistenceStrategy_->storeItem(id(), dataFilename, dataVec);
220 persistenceStrategy_->storeItem(id(), metadataFilename, metadataVec);
221 }
222
223 statistics.recordedData++;
224 statistics.recordedMetaData++;
225
226 return dataToReturn;
227 }
228} // namespace armarx::armem::server::ltm
#define ARMARX_CHECK_EMPTY(c)
MemoryID cleanID() const
Definition MemoryID.cpp:133
std::string str(bool escapeDelimiters=true) const
Get a string representation of this memory ID.
Definition MemoryID.cpp:102
EntityInstanceT & addInstance(const EntityInstanceT &instance)
Add a single instance with data.
nlohmann::json _implStore(const armem::wm::EntityInstance &wmEntityInstance) override
void _implLoadAllReferences(armem::wm::EntitySnapshot &wmEntitySnapshot) const override
void _implResolve(armem::wm::EntityInstance &wmEntitySnapshot) const override
EntityInstance(const std::string &exportName, const MemoryID &memoryId, const std::shared_ptr< Processors > &filters, const std::shared_ptr< persistence::MemoryPersistenceStrategy > &persistenceStrategy)
std::shared_ptr< Processors > processors
Definition MemoryItem.h:54
Client-side working entity instance.
Client-side working memory entity snapshot.
The Path class.
Definition Path.h:36
#define ARMARX_CHECK_NOT_NULL(ptr)
This macro evaluates whether ptr is not null and if it turns out to be false it will throw an Express...
#define ARMARX_ERROR
The logging level for unexpected behaviour, that must be fixed.
Definition Logging.h:194
#define ARMARX_DEBUG
The logging level for output that is only interesting while debugging.
Definition Logging.h:182
#define ARMARX_WARNING
The logging level for unexpected behaviour, but not a serious problem.
Definition Logging.h:191
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
std::shared_ptr< Dict > DictPtr
Definition Dict.h:42
std::string origin
Indicates the source of the instance e.g. from a specific LTM.
#define ARMARX_TRACE
Definition trace.h:75