25 std::string exportPath =
p.export_path;
27 std::string persistenceStrategiesStr =
p.persistenceStrategies;
29 ARMARX_INFO <<
"Persistence strategies=" << persistenceStrategiesStr;
31 std::vector<std::string> persistenceStrategies = split(persistenceStrategiesStr,
',');
33 ARMARX_INFO <<
"Found " << persistenceStrategies.size() <<
" persistence strategies";
36 std::string identifiersStr =
p.persistenceStrategyIdentifier;
37 std::vector<std::string>
identifiers = split(identifiersStr,
',');
38 std::string identifier =
"defaultStrategy";
39 ARMARX_INFO <<
"Persistence identifiers=" << identifiersStr;
43 std::shared_ptr<armem::server::ltm::persistence::RedundantPersistenceStrategy>
44 redundantPersistence =
45 std::make_shared<armem::server::ltm::persistence::RedundantPersistenceStrategy>();
48 for (
size_t i = 0; i < persistenceStrategies.size(); i++)
50 std::string s = persistenceStrategies.at(i);
64 ARMARX_INFO <<
"Min available disk space=" <<
p.minDiskSpace;
66 std::shared_ptr<armem::server::ltm::persistence::DiskPersistence> diskPersistence =
67 std::make_shared<armem::server::ltm::persistence::DiskPersistence>(
68 std::filesystem::path(exportPath));
69 diskPersistence->setIdentifier(identifier);
71 diskPersistence->setMinAvailableDiskSpace(
p.minDiskSpace);
74 if (
p.compressionEnabled)
76 diskPersistence->setCompressionLevel(
p.compressionLevel);
77 diskPersistence->setCompressionMinBytes(
78 static_cast<std::size_t
>(
p.compressionMinBytes));
79 diskPersistence->setCompressionEnabled(
true);
80 ARMARX_INFO <<
"LTM export compression enabled: gzip level "
81 <<
p.compressionLevel <<
" for payloads >= "
82 <<
p.compressionMinBytes <<
" bytes";
86 if (
p.batchWriteEnabled)
88 diskPersistence->setBatchSizeThreshold(
static_cast<size_t>(
p.batchSizeThreshold));
89 diskPersistence->setBatchTimeThresholdMs(
static_cast<size_t>(
p.batchTimeThresholdMs));
90 diskPersistence->setBatchWriteEnabled(
true);
91 ARMARX_INFO <<
"Batch write mode enabled: threshold=" <<
p.batchSizeThreshold
92 <<
" items or " <<
p.batchTimeThresholdMs <<
"ms";
95 redundantPersistence->addStrategy(diskPersistence);
100 ARMARX_WARNING <<
"Persistence strategy=" << s <<
" currently deactivated";
121 else if (s ==
"mongodb")
124 ARMARX_WARNING <<
"Persistence strategy=" << s <<
" not implemented";
148 const std::string& exportName,
149 const std::string& memoryName,
150 const std::shared_ptr<persistence::RedundantPersistenceStrategy>& persistenceStrategy) :
154 persistenceStrategy_(persistenceStrategy)
163 if (persistenceStrategy_)
165 persistenceStrategy_->setExportName(memoryName);
183 ARMARX_IMPORTANT <<
"Storing of data finished, starting to generate and save statistics...";
207 for (
auto& core_segment : persistenceStrategy_->getContainerKeys(
id()))
211 std::shared_ptr<persistence::MemoryPersistenceStrategy> coreSegmentPersistenceStrategy(
212 persistenceStrategy_);
215 id().withCoreSegmentName(core_segment),
217 coreSegmentPersistenceStrategy);
231 persistenceStrategy_->containsContainer(
id(), coreSegmentName);
233 return foundCoreSegment;
236 std::shared_ptr<CoreSegment>
246 std::shared_ptr<persistence::MemoryPersistenceStrategy> coreSegmentPersistenceStrategy(
247 persistenceStrategy_);
250 id().withCoreSegmentName(coreSegmentName),
252 coreSegmentPersistenceStrategy);
274 [&wmMemory](
auto& ltmCoreSegment)
277 ltmCoreSegment.loadAllReferences(wmCoreSegment);
284 existingWmCoreSegment.
append(wmCoreSegment);
304 [&wmMemory, &coreSegmentNames](
auto& ltmCoreSegment)
307 (std::find(coreSegmentNames.begin(),
308 coreSegmentNames.end(),
309 ltmCoreSegment.id().coreSegmentName) != coreSegmentNames.end());
313 ltmCoreSegment.loadAllReferences(wmCoreSegment);
320 existingWmCoreSegment.
append(wmCoreSegment);
329 ARMARX_DEBUG <<
"Skipping loading CoreSegment with name "
331 <<
" from LTM into WM as it is not in the defined list";
342 ARMARX_DEBUG <<
"Memory: Load latest N references for all core segments (id="
346 [&wmMemory, &n](
auto& ltmCoreSegment)
349 ltmCoreSegment.loadLatestNReferences(n, wmCoreSegment);
356 existingWmCoreSegment.
append(wmCoreSegment);
368 std::list<std::string> coreSegNames)
373 ARMARX_DEBUG <<
"Memory: Load latest references for set of core segments (id="
377 [&wmMemory, &n, &coreSegNames](
auto& ltmCoreSegment)
380 (std::find(coreSegNames.begin(),
382 ltmCoreSegment.id().coreSegmentName) != coreSegNames.end());
385 ARMARX_DEBUG <<
"Load core segment=" << ltmCoreSegment.id().coreSegmentName;
387 ltmCoreSegment.loadLatestNReferences(n, wmCoreSegment);
394 existingWmCoreSegment.
append(wmCoreSegment);
403 ARMARX_DEBUG <<
"Skipping loading CoreSegment with name "
405 <<
" from LTM into WM as it is not in the defined list";
418 [&](
auto& wmCoreSegment)
420 std::shared_ptr<persistence::MemoryPersistenceStrategy>
421 coreSegmentPersistenceStrategy(persistenceStrategy_);
425 id().withCoreSegmentName(wmCoreSegment.id().coreSegmentName),
427 coreSegmentPersistenceStrategy);
429 ltmCoreSegment.
resolve(wmCoreSegment);
445 if (
id().memoryName.empty())
448 <<
"During storage of memory '" << wmMemory.
id().
str()
449 <<
"' I noticed that the corresponding LTM has no id set. "
450 <<
"I set the id of the LTM to the same name, however this should not happen!";
458 [&](
const auto& wmCoreSegment)
460 std::shared_ptr<persistence::MemoryPersistenceStrategy>
461 coreSegmentPersistenceStrategy(persistenceStrategy_);
465 id().withCoreSegmentName(wmCoreSegment.id().coreSegmentName),
467 coreSegmentPersistenceStrategy);
470 ltmCoreSegment.
store(wmCoreSegment, simulatedVersion);
481 std::shared_ptr<armem::wm::Memory>
483 uint64_t& filteredCount,
484 uint64_t& passedCount)
495 memory.forEachCoreSegment([&](
const auto& cs) {
496 cs.forEachProviderSegment([&](
const auto& ps) {
497 ps.forEachEntity([&](
const auto& entity) {
498 entity.forEachSnapshot([&](
const auto&) {
506 return std::make_shared<armem::wm::Memory>(
memory);
510 auto filteredMemory = std::make_shared<armem::wm::Memory>(
memory.id());
513 memory.forEachCoreSegment([&](
const auto& wmCoreSegment) {
514 wmCoreSegment.forEachProviderSegment([&](
const auto& wmProviderSegment) {
515 wmProviderSegment.forEachEntity([&](
const auto& wmEntity) {
516 wmEntity.forEachSnapshot([&](
const auto& wmSnapshot) {
518 bool accepted =
processors->acceptSnapshotForSegment(
519 wmCoreSegment.name(), wmProviderSegment.name(), wmSnapshot,
false);
525 auto& cs = filteredMemory->hasCoreSegment(wmCoreSegment.name())
526 ? filteredMemory->getCoreSegment(wmCoreSegment.name())
527 : filteredMemory->addCoreSegment(wmCoreSegment.name());
529 auto& ps = cs.hasProviderSegment(wmProviderSegment.name())
530 ? cs.getProviderSegment(wmProviderSegment.name())
531 : cs.addProviderSegment(wmProviderSegment.name());
533 auto& entity = ps.hasEntity(wmEntity.name())
534 ? ps.getEntity(wmEntity.name())
535 : ps.addEntity(wmEntity.name());
537 entity.addSnapshot(wmSnapshot);
549 ARMARX_DEBUG <<
"Pre-filter: " << passedCount <<
" passed, "
550 << filteredCount <<
" filtered out";
552 return filteredMemory;
581 auto firstTimeStarted = this->
statistics.firstStarted;
582 if (!firstTimeStarted.isValid())
585 ARMARX_DEBUG <<
"No Statistics will be saved because firstStarted is invalid: "
594 if (first_stats.empty())
597 ARMARX_DEBUG <<
"No Statistics will be saved because no actual data was recorded.";
600 std::map<std::string,
601 std::map<std::string, ltm::processor::SnapshotFilter::FilterStatistics>>
603 std::map<std::string, armarx::core::time::DateTime> times;
609 information[
"LTM"] = first_stats;
613 ARMARX_DEBUG <<
"Something went wrong after getting the statistics";
629 ARMARX_DEBUG <<
"Something went wrong with the statistics saving process";
633 std::vector<std::string>
634 Memory::split(std::string
str,
char delimiter)
638 std::stringstream ss(
str);
639 std::vector<std::string> res;
641 while (std::getline(ss, token, delimiter))
643 res.push_back(token);
std::string coreSegmentName
MemoryID getMemoryID() const
std::string str(bool escapeDelimiters=true) const
Get a string representation of this memory ID.
void append(const OtherDerivedT &other)
bool forEachCoreSegment(CoreSegmentFunctionT &&func)
bool hasCoreSegment(const std::string &name) const
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.
std::vector< std::string > getCoreSegmentNames() const
CoreSegmentT & getCoreSegment(const std::string &name)
void getAndSaveStatistics()
getAndSaveStatistics generates and saves statistics for a LTM recording
void _setMemoryID(const MemoryID &memoryId) final
void _enqueueForAsyncStorage(std::shared_ptr< const armem::wm::Memory > memory) final
void _resolve(armem::wm::Memory &wmMemory) final
detail::mixin::BufferedMemoryMixin< CoreSegment > BufferedBase
detail::mixin::CachedMemoryMixin< CoreSegment > CachedBase
void _loadLatestNReferences(int n, armem::wm::Memory &wmMemory) final
void _directlyStore(const armem::wm::Memory &wmMemory, bool simulatedVersion) final
void _setExportName(const std::string &memoryName) final
bool _implHasCoreSegment(const std::string &coreSegmentName) const final
bool _implForEachCoreSegment(std::function< void(CoreSegment &)> func) const final
std::shared_ptr< armem::wm::Memory > _preFilterMemory(const armem::wm::Memory &memory, uint64_t &filteredCount, uint64_t &passedCount) final
Pre-filter a memory object before enqueuing for async storage.
void setPersistenceStrategy(std::shared_ptr< persistence::RedundantPersistenceStrategy > persistenceStrategy)
std::shared_ptr< CoreSegment > _implFindCoreSegment(const std::string &coreSegmentName) const final
void _loadAllReferences(armem::wm::Memory &wmMemory) final
void _store(const armem::wm::Memory &wmMemory) final
void _loadOnStartup() final
void createPropertyDefinitions(PropertyDefinitionsPtr &defs, const std::string &prefix) override
default parameters. Implementation should use the configuration to configure
void _configure(const nlohmann::json &config) final
configuration
void _enqueuePendingConversion(detail::mixin::PendingConversion pending) final
detail::MemoryBase< CoreSegment > MemoryBase
void store(const armem::wm::CoreSegment &coreSeg, bool simulatedVersion)
encode the content of a wm::Memory and store
void resolve(armem::wm::CoreSegment &coreSeg)
convert the references of the input into a wm::Memory
virtual void createPropertyDefinitions(PropertyDefinitionsPtr &defs, const std::string &prefix)
bool forEachCoreSegment(std::function< void(CoreSegmentT &)> func) const
struct armarx::armem::server::ltm::detail::MemoryBase::Properties p
Statistics getStatistics() const
std::map< std::string, processor::SnapshotFilter::FilterStatistics > getFilterStatistics()
MemoryID getMemoryID() const
virtual std::string getExportName() const
void setMemoryID(const MemoryID &)
std::shared_ptr< Processors > processors
void createPropertyDefinitions(PropertyDefinitionsPtr &defs, const std::string &prefix)
void addToBuffer(const armem::wm::Memory &memory)
void configureMixin(const nlohmann::json &json)
void enqueuePendingConversion(PendingConversion pending)
void enqueueForAsyncStoragePublic(std::shared_ptr< const armem::wm::Memory > memory)
void setMixinMemoryID(const MemoryID &id)
bool cacheHasCoreSegment(const std::string &n) const
void configureMixin(const nlohmann::json &json)
void setMixinMemoryID(const MemoryID &id)
Client-side working memory core segment.
Client-side working memory.
Brief description of class memory.
#define ARMARX_INFO
The normal logging level.
#define ARMARX_IMPORTANT
The logging level for always important information, but expected behaviour (in contrast to ARMARX_WAR...
#define ARMARX_DEBUG
The logging level for output that is only interesting while debugging.
#define ARMARX_WARNING
The logging level for unexpected behaviour, but not a serious problem.
const std::list< std::string > identifiers
auto make_shared(Args &&... args)
IceUtil::Handle< class PropertyDefinitionContainer > PropertyDefinitionsPtr
PropertyDefinitions smart pointer type.
Holds snapshots and metadata for deferred conversion in async thread This allows us to defer the expe...