8#include <IceUtil/Time.h>
45 std::vector<ltm::detail::mixin::PendingConversion::SegmentMetadata>
46 extractSegmentMetadata(
const wm::Memory& structure,
47 const std::vector<wm::EntitySnapshot>& snapshots)
49 std::vector<ltm::detail::mixin::PendingConversion::SegmentMetadata> metadata;
52 std::map<std::string, std::set<std::string>> segmentMap;
53 for (
const auto& snapshot : snapshots)
55 segmentMap[snapshot.id().coreSegmentName].insert(snapshot.id().providerSegmentName);
59 for (
const auto& [coreSegmentName, providerNames] : segmentMap)
64 ARMARX_WARNING <<
"Core segment not found in structure: " << coreSegmentName;
70 meta.coreSegmentAronType = coreStructure->aronType();
72 for (
const auto& providerName : providerNames)
74 auto* providerStructure = coreStructure->findProviderSegment(providerName);
75 if (providerStructure)
77 meta.providerSegmentAronTypes[providerName] = providerStructure->aronType();
81 metadata.push_back(std::move(meta));
107 data::AddSegmentResult
113 ARMARX_DEBUG <<
"Adding segment using MemoryToIceAdapter";
115 data::AddSegmentResult output;
120 coreSegment = &
workingMemory->getCoreSegment(input.coreSegmentName);
126 coreSegment = &
workingMemory->addCoreSegment(input.coreSegmentName);
130 output.success =
false;
131 output.errorMessage = e.what();
137 if (input.providerSegmentName.size() > 0)
140 [&coreSegment, &input]()
149 if (input.clearWhenExists)
164 output.success =
true;
165 output.segmentID = segmentID.
str();
169 data::AddSegmentsResult
175 data::AddSegmentsResult output;
176 for (
const auto& i : input)
178 output.push_back(
addSegment(i, addCoreSegments));
188 auto handleException = [](
const std::string& what)
190 data::CommitResult result;
191 data::EntityUpdateResult& r = result.results.emplace_back();
193 r.errorMessage = what;
202 catch (
const Ice::Exception& e)
204 return handleException(e.what());
206 catch (
const std::exception& e)
215 return handleException(e.what());
219 data::CommitResult resultIce;
220 toIce(resultIce, result);
236 return this->_commit(
commit,
false);
244 auto handleException = [](
const std::string& what)
246 data::CommitResult result;
247 data::EntityUpdateResult& r = result.results.emplace_back();
249 r.errorMessage = what;
258 catch (
const Ice::Exception& e)
260 return handleException(e.what());
262 catch (
const std::exception& e)
271 return handleException(e.what());
275 data::CommitResult resultIce;
276 toIce(resultIce, result);
292 return this->_commit(
commit,
true);
296 MemoryToIceAdapter::_commit(
const armem::Commit& commit,
bool locking)
302 auto commitStartTime = std::chrono::steady_clock::now();
304 IceUtil::Time startTime;
308 startTime = IceUtil::Time::now();
315 std::vector<data::MemoryID> updatedIDs;
324 IceUtil::Time updateStartTime;
327 updateStartTime = IceUtil::Time::now();
342 IceUtil::Time updateEndTime = IceUtil::Time::now();
343 IceUtil::Time updateElapsed = updateEndTime - updateStartTime;
344 float updateElapsedMs = updateElapsed.toMilliSecondsDouble();
347 debugObserver->setDebugChannel(
350 {
"Memory | Commit | updateResult step [ms]",
new armarx::Variant(updateElapsedMs)},
354 for (
const auto& snapshot : updateResult.removedSnapshots)
356 ARMARX_DEBUG <<
"The id " << snapshot.id() <<
" was removed from wm";
370 IceUtil::Time storeStartTime;
373 storeStartTime = IceUtil::Time::now();
377 auto segmentMetadata = extractSegmentMetadata(*
workingMemory, updateResult.updatedSnapshots);
383 updateResult.updatedSnapshots,
388 IceUtil::Time storeEndTime = IceUtil::Time::now();
389 IceUtil::Time storeElapsed = storeEndTime - storeStartTime;
390 float storeElapsedMs = storeElapsed.toMilliSecondsDouble();
393 debugObserver->setDebugChannel(
396 {
"Memory | Commit | LTM enqueue (CONSOLIDATE_ALL) [ms]",
new armarx::Variant(storeElapsedMs)},
413 IceUtil::Time storeStartTime;
416 storeStartTime = IceUtil::Time::now();
420 auto segmentMetadata = extractSegmentMetadata(*
workingMemory, updateResult.removedSnapshots);
426 updateResult.removedSnapshots,
431 IceUtil::Time storeEndTime = IceUtil::Time::now();
432 IceUtil::Time storeElapsed = storeEndTime - storeStartTime;
433 float storeElapsedMs = storeElapsed.toMilliSecondsDouble();
436 debugObserver->setDebugChannel(
439 {
"Memory | Commit | LTM enqueue (CONSOLIDATE_REMOVED) [ms]",
new armarx::Variant(storeElapsedMs)},
453 data::MemoryID&
id = updatedIDs.emplace_back();
457 catch (
const error::ArMemError& e)
461 statistics.failedUpdates.fetch_add(1, std::memory_order_relaxed);
463 catch (
const aron::error::AronException& e)
467 statistics.failedUpdates.fetch_add(1, std::memory_order_relaxed);
469 catch (
const Ice::Exception& e)
473 statistics.failedUpdates.fetch_add(1, std::memory_order_relaxed);
484 statistics.failedUpdates.fetch_add(1, std::memory_order_relaxed);
494 auto commitEndTime = std::chrono::steady_clock::now();
495 double commitBlockingTimeMs = std::chrono::duration<double, std::milli>(commitEndTime - commitStartTime).count();
499 double currentTotal = statistics.totalCommitBlockingTimeMs.load(std::memory_order_relaxed);
500 statistics.totalCommitBlockingTimeMs.store(currentTotal + commitBlockingTimeMs, std::memory_order_relaxed);
502 double currentMax = statistics.maxCommitBlockingTimeMs.load(std::memory_order_relaxed);
503 while (commitBlockingTimeMs > currentMax)
505 if (statistics.maxCommitBlockingTimeMs.compare_exchange_weak(currentMax, commitBlockingTimeMs, std::memory_order_relaxed))
514 IceUtil::Time endTime = IceUtil::Time::now();
515 IceUtil::Time elapsed = endTime - startTime;
516 float elapsedMs = elapsed.toMilliSecondsDouble();
519 auto [commitsPerSec, queriesPerSec] = statistics.updateRates();
524 debugObserver->setDebugChannel(
528 {
"Memory | Commit | t blocked [ms]",
new armarx::Variant(elapsedMs)},
529 {
"Memory | Commit | max blocked [ms]",
new armarx::Variant(
static_cast<float>(statistics.maxCommitBlockingTimeMs.load()))},
531 {
"Memory | writes/sec",
new armarx::Variant(
static_cast<float>(commitsPerSec))},
532 {
"Memory | reads/sec",
new armarx::Variant(
static_cast<float>(queriesPerSec))},
534 {
"Memory | total commits",
new armarx::Variant(
static_cast<int>(statistics.totalCommitCount.load()))},
535 {
"Memory | total entity updates",
new armarx::Variant(
static_cast<int>(statistics.totalEntityUpdates.load()))},
536 {
"Memory | successful updates",
new armarx::Variant(
static_cast<int>(statistics.successfulUpdates.load()))},
537 {
"Memory | failed updates",
new armarx::Variant(
static_cast<int>(statistics.failedUpdates.load()))},
539 {
"Memory | LTM async queue size",
new armarx::Variant(
static_cast<int>(queueSize))},
548 armem::query::data::Result
556 auto queryStartTime = std::chrono::steady_clock::now();
559 statistics.totalQueryCount.fetch_add(1, std::memory_order_relaxed);
566 armem::query::data::Result result;
571 result.success =
true;
572 if (result.memory->coreSegments.size() == 0)
578 auto queryEndTime = std::chrono::steady_clock::now();
579 double queryBlockingTimeMs = std::chrono::duration<double, std::milli>(queryEndTime - queryStartTime).count();
583 double currentTotal = statistics.totalQueryBlockingTimeMs.load(std::memory_order_relaxed);
584 statistics.totalQueryBlockingTimeMs.store(currentTotal + queryBlockingTimeMs, std::memory_order_relaxed);
586 double currentMax = statistics.maxQueryBlockingTimeMs.load(std::memory_order_relaxed);
587 while (queryBlockingTimeMs > currentMax)
589 if (statistics.maxQueryBlockingTimeMs.compare_exchange_weak(currentMax, queryBlockingTimeMs, std::memory_order_relaxed))
601 debugObserver->setDebugChannel(
604 {
"Memory | Query | t blocked [ms]",
new armarx::Variant(
static_cast<float>(queryBlockingTimeMs))},
605 {
"Memory | Query | max blocked [ms]",
new armarx::Variant(
static_cast<float>(statistics.maxQueryBlockingTimeMs.load()))},
606 {
"Memory | total queries",
new armarx::Variant(
static_cast<int>(statistics.totalQueryCount.load()))},
613 armem::query::data::Result
636 armem::query::data::Result result;
640 result.success =
true;
641 if (result.memory->coreSegments.size() == 0)
657 armem::structure::data::GetServerStructureResult
664 armem::structure::data::GetServerStructureResult ret;
675 if (query_result.success)
677 structure.
append(query_result.memory);
693 ARMARX_INFO <<
"Reloading of all core segments from LTM into WM triggered";
695 int maxAmountOfSnapshots = this->
longtermMemory->p.maxAmountOfSnapshotsLoaded;
698 this->
longtermMemory->loadLatestNReferences(maxAmountOfSnapshots, m);
702 auto res = this->
commit(com);
713 ARMARX_INFO <<
"Reloading of specific core segments from LTM into WM triggered";
715 std::ostringstream namesStr;
716 for (
auto it = coreSegmentNames.begin(); it != coreSegmentNames.end(); ++it)
718 if (it != coreSegmentNames.begin())
723 ARMARX_INFO <<
"Loading core segments=" << namesStr.str();
726 int maxAmountOfSnapshots = this->
longtermMemory->p.maxAmountOfSnapshotsLoaded;
729 this->
longtermMemory->loadLatestNReferences(maxAmountOfSnapshots, m, coreSegmentNames);
733 auto res = this->
commit(com);
742 ARMARX_INFO <<
"Reloading of coresegment defined in 'loadedCoreSegments' from LTM into WM "
743 "on startup triggered";
747 ARMARX_INFO <<
"Loading core segments=" << coreNames
748 <<
" defined in property 'loadedCoreSegments'";
751 std::list<std::string> names;
752 std::stringstream ss(coreNames);
755 while (std::getline(ss, item,
','))
757 names.push_back(item);
769 ARMARX_INFO <<
"Reloading of data from LTM into WM on startup triggered";
777 ARMARX_INFO <<
"Not loading initial data from LTM due to importOnStartup being "
785 dto::DirectlyStoreResult
791 dto::DirectlyStoreResult output;
792 output.success =
true;
800 dto::StartRecordResult
808 dto::StartRecordResult ret;
814 dto::StopRecordResult
824 ARMARX_INFO <<
"Starting to save left-over WM data into LTM";
830 ARMARX_INFO <<
"Not storing WM data into LTM on stop, because storeOnStop is "
840 std::thread flushThread(
847 ARMARX_INFO <<
"All pending data stored successfully";
853 ltm->bufferFinished();
855 flushThread.detach();
858 <<
"Stopped all LTM recordings, flushing async queue in background. "
859 <<
"Please wait with stopping the component until all files are written";
861 dto::StopRecordResult ret;
867 dto::RecordStatusResult
870 dto::RecordStatusResult ret;
879 [&savedSnapshots, &totalSnapshots](
const auto&
c)
881 c.forEachProviderSegment(
882 [&savedSnapshots, &totalSnapshots](
const auto& p)
885 [&savedSnapshots, &totalSnapshots](
const auto& e)
887 savedSnapshots += e.getStatistics().recordedSnapshots;
889 e.forEachSnapshot([&totalSnapshots](
const auto&)
890 { totalSnapshots++; });
895 ret.status.savedSnapshots = savedSnapshots;
896 ret.status.totalSnapshots = totalSnapshots;
902 prediction::data::PredictionResultSeq
910 prediction::data::EngineSupportMap
913 prediction::data::EngineSupportMap result;
950 auto [commitsPerSec, queriesPerSec] = statistics.updateRates();
954 const size_t numThreadsProcessing =
longtermMemory->getNumThreadsProcessing();
955 const auto& asyncStats =
longtermMemory->getAsyncStorageStatistics();
956 const uint64_t asyncItemsEnqueued =
957 asyncStats.totalItemsEnqueued.load(std::memory_order_relaxed);
958 const uint64_t asyncItemsProcessed =
959 asyncStats.totalItemsProcessed.load(std::memory_order_relaxed);
960 const uint64_t asyncSnapshotsStored =
961 asyncStats.totalSnapshotsStored.load(std::memory_order_relaxed);
964 const uint64_t asyncSnapshotsDropped = asyncStats.totalSnapshotsDropped();
965 const uint64_t asyncSnapshotsDroppedBackpressure =
966 asyncStats.snapshotsDroppedBackpressure.load(std::memory_order_relaxed);
967 const uint64_t asyncBackpressureEvents =
968 asyncStats.backpressureEvents.load(std::memory_order_relaxed);
969 const double asyncAvgStorageTimeMs = asyncStats.getAvgStorageTimeMs();
970 const double asyncMaxStorageTimeMs = asyncStats.getMaxStorageTimeMs();
973 uint64_t commitCount = statistics.totalCommitCount.load(std::memory_order_relaxed);
974 uint64_t queryCount = statistics.totalQueryCount.load(std::memory_order_relaxed);
975 double avgCommitBlockingMs = commitCount > 0
976 ? statistics.totalCommitBlockingTimeMs.load(std::memory_order_relaxed) / commitCount
978 double avgQueryBlockingMs = queryCount > 0
979 ? statistics.totalQueryBlockingTimeMs.load(std::memory_order_relaxed) / queryCount
983 debugObserver->setDebugChannel(
987 {
"Memory | writes/sec",
new armarx::Variant(
static_cast<float>(commitsPerSec))},
988 {
"Memory | reads/sec",
new armarx::Variant(
static_cast<float>(queriesPerSec))},
990 {
"Memory | total commits",
new armarx::Variant(
static_cast<int>(statistics.totalCommitCount.load()))},
991 {
"Memory | total queries",
new armarx::Variant(
static_cast<int>(statistics.totalQueryCount.load()))},
992 {
"Memory | total entity updates",
new armarx::Variant(
static_cast<int>(statistics.totalEntityUpdates.load()))},
993 {
"Memory | successful updates",
new armarx::Variant(
static_cast<int>(statistics.successfulUpdates.load()))},
994 {
"Memory | failed updates",
new armarx::Variant(
static_cast<int>(statistics.failedUpdates.load()))},
996 {
"Memory | Commit | avg blocked [ms]",
new armarx::Variant(
static_cast<float>(avgCommitBlockingMs))},
997 {
"Memory | Commit | max blocked [ms]",
new armarx::Variant(
static_cast<float>(statistics.maxCommitBlockingTimeMs.load()))},
998 {
"Memory | Query | avg blocked [ms]",
new armarx::Variant(
static_cast<float>(avgQueryBlockingMs))},
999 {
"Memory | Query | max blocked [ms]",
new armarx::Variant(
static_cast<float>(statistics.maxQueryBlockingTimeMs.load()))},
1001 {
"Memory | LTM async queue size",
new armarx::Variant(
static_cast<int>(queueSize))},
1002 {
"Memory | LTM threads processing",
new armarx::Variant(
static_cast<int>(numThreadsProcessing))},
1003 {
"Memory | LTM items enqueued",
new armarx::Variant(
static_cast<int>(asyncItemsEnqueued))},
1004 {
"Memory | LTM items processed",
new armarx::Variant(
static_cast<int>(asyncItemsProcessed))},
1005 {
"Memory | LTM snapshots stored",
new armarx::Variant(
static_cast<int>(asyncSnapshotsStored))},
1006 {
"Memory | LTM snapshots dropped",
new armarx::Variant(
static_cast<int>(asyncSnapshotsDropped))},
1007 {
"Memory | LTM snapshots dropped (backpressure)",
new armarx::Variant(
static_cast<int>(asyncSnapshotsDroppedBackpressure))},
1008 {
"Memory | LTM backpressure events",
new armarx::Variant(
static_cast<int>(asyncBackpressureEvents))},
1009 {
"Memory | LTM avg storage [ms]",
new armarx::Variant(
static_cast<float>(asyncAvgStorageTimeMs))},
1010 {
"Memory | LTM max storage [ms]",
new armarx::Variant(
static_cast<float>(asyncMaxStorageTimeMs))},
SpamFilterDataPtr deactivateSpam(SpamFilterDataPtr const &spamFilter, float deactivationDurationSec, const std::string &identifier, bool deactivate)
The Variant class is described here: Variants.
std::string coreSegmentName
std::string str(bool escapeDelimiters=true) const
Get a string representation of this memory ID.
std::string providerSegmentName
ProviderSegmentT & getProviderSegment(const std::string &name)
CoreSegmentT * findCoreSegment(const std::string &name)
void append(const OtherDerivedT &other)
Merge another memory into this one.
std::vector< UpdateResult > update(const Commit &commit, const bool addMissingCoreSegmentDuringUpdate=false, const bool checkMemoryName=true)
Store all updates in commit.
void all()
Get all snapshots from all entities in all segments.
QueryInput buildQueryInput() const
Indicates that a name in a given ID does not match a container's own name.
Indicates that a container did not have an entry under a given name.
server::wm::Memory * workingMemory
armem::structure::data::GetServerStructureResult getServerStructure()
void setMemoryListener(client::MemoryListenerInterfacePrx memoryListenerTopic)
dto::StartRecordResult startRecord(const dto::StartRecordInput &startRecordInput)
armem::CommitResult reloadFromLTMOnStartup()
Triggers a reload (.
armem::CommitResult reloadAllFromLTM()
Loads all core segments and their data from the LTM.
query::data::Result queryLTM(const armem::query::data::Input &input, bool storeIntoWM)
Query the LTMs of the memory server.
client::MemoryListenerInterfacePrx memoryListenerTopic
dto::StopRecordResult stopRecord()
query::data::Result query(const armem::query::data::Input &input)
armem::CommitResult reloadCoreSegmentsFromLTM(std::list< std::string > &coreSegmentname)
Only load specific core segments and their data from the LTM.
prediction::data::PredictionResultSeq predict(prediction::data::PredictionRequestSeq requests)
dto::DirectlyStoreResult directlyStore(const dto::DirectlyStoreInput &directlStoreInput)
void reportDebugMetrics()
Report all debug metrics to the debug observer.
armem::CommitResult reloadPropertyDefinedCoreSegmentsFromLTM()
server::ltm::Memory * longtermMemory
data::AddSegmentResult addSegment(const data::AddSegmentInput &input, bool addCoreSegments=false)
dto::RecordStatusResult getRecordStatus()
data::CommitResult commitLocking(const data::Commit &commitIce, Time timeArrived)
prediction::data::EngineSupportMap getAvailableEngines()
data::AddSegmentsResult addSegments(const data::AddSegmentsInput &input, bool addCoreSegments=false)
data::CommitResult commit(const data::Commit &commitIce, Time timeArrived)
MemoryToIceAdapter(server::wm::Memory *workingMemory, server::ltm::Memory *longtermMemory)
Construct a MemoryToIceAdapter from an existing Memory.
A memory storing data on the hard drive and in mongodb (needs 'armarx memory start' to start the mong...
DebugObserverInterfacePrx getDebugObserver() const
Get the current debug observer (may be nullptr)
ResultMemoryT process(const armem::query::data::Input &input, const MemoryT &memory) const
ResultMemoryT process(const armem::query::data::Input &input, const MemoryT &memory) const
ProviderSegment & addProviderSegment(const std::string &name, Args... args)
auto doLockedExclusive(FunctionT &&function)
Execute function under exclusive (write) lock.
std::vector< Base::UpdateResult > updateLocking(const Commit &commit)
Perform the commit, locking the core segments.
Client-side working memory.
#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_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_ERROR
The logging level for unexpected behaviour, that must be fixed.
#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.
#define TIMING_START(name)
Helper macro to do timing tests.
#define TIMING_END_STREAM(name, os)
Prints duration.
query::Builder QueryBuilder
@ NoData
Just get the structure, but no ARON data.
DataMode boolToDataMode(bool withData)
void fromIce(const data::MemoryID &ice, MemoryID &id)
armarx::core::time::DateTime Time
Commit toCommit(const ContainerT &container)
void toIce(data::MemoryID &ice, const MemoryID &id)
std::string GetHandledExceptionString()
void fromIce(const std::map< IceKeyT, IceValueT > &iceMap, boost::container::flat_map< CppKeyT, CppValueT > &cppMap)
void toIce(std::map< IceKeyT, IceValueT > &iceMap, const boost::container::flat_map< CppKeyT, CppValueT > &cppMap)
std::vector< EntityUpdateResult > results
A bundle of updates to be sent to the memory.
Result of an EntityUpdate.
An update of an entity for a specific point in time.
static QueryResult fromIce(const armem::query::data::Result &ice)
std::atomic< uint64_t > totalEntityUpdates
std::atomic< uint64_t > successfulUpdates
std::atomic< uint64_t > totalCommitCount