From 07611ad812a6865b3b0f482d4b50c3ad164a29a1 Mon Sep 17 00:00:00 2001
From: Fabian Peller-Konrad <fabian.peller-konrad@kit.edu>
Date: Fri, 22 Oct 2021 09:55:52 +0200
Subject: [PATCH] ltm implementation for disk memory, new interfaces,
 connection to query_proc

---
 .../RobotAPI/libraries/armem/CMakeLists.txt   |  73 +++--
 .../armem/core/wm/aron_conversions.cpp        |  59 ++--
 .../armem/core/wm/aron_conversions.h          |   7 +-
 .../armem/server/MemoryToIceAdapter.cpp       |  12 +-
 .../armem/server/MemoryToIceAdapter.h         |   2 +-
 .../armem/server/ltm/LongtermMemoryBase.cpp   | 100 -------
 .../armem/server/ltm/LongtermMemoryBase.h     |  69 -----
 .../server/ltm/detail/BufferedMemoryBase.cpp  |   7 +
 .../server/ltm/detail/BufferedMemoryBase.h    |  45 +++
 .../server/ltm/detail/CoreSegmentBase.cpp     |   6 +
 .../armem/server/ltm/detail/CoreSegmentBase.h |  56 ++++
 .../armem/server/ltm/detail/EntityBase.cpp    |  10 +
 .../armem/server/ltm/detail/EntityBase.h      |  58 ++++
 .../server/ltm/detail/EntitySnapshotBase.cpp  |  14 +
 .../server/ltm/detail/EntitySnapshotBase.h    |  36 +++
 .../armem/server/ltm/detail/LUTMemoryBase.cpp |   6 +
 .../armem/server/ltm/detail/LUTMemoryBase.h   |  47 +++
 .../armem/server/ltm/detail/MemoryBase.cpp    |   6 +
 .../armem/server/ltm/detail/MemoryBase.h      |  55 ++++
 .../armem/server/ltm/detail/MemoryItem.cpp    |  28 ++
 .../armem/server/ltm/detail/MemoryItem.h      |  27 ++
 .../server/ltm/detail/ProviderSegmentBase.cpp |  11 +
 .../server/ltm/detail/ProviderSegmentBase.h   |  56 ++++
 .../armem/server/ltm/disk/CoreSegment.cpp     | 100 +++++++
 .../armem/server/ltm/disk/CoreSegment.h       |  33 ++
 .../armem/server/ltm/disk/Entity.cpp          | 148 +++++++++
 .../libraries/armem/server/ltm/disk/Entity.h  |  43 +++
 .../armem/server/ltm/disk/EntitySnapshot.cpp  | 131 ++++++++
 .../armem/server/ltm/disk/EntitySnapshot.h    |  28 ++
 .../armem/server/ltm/disk/Memory.cpp          | 142 +++++++++
 .../libraries/armem/server/ltm/disk/Memory.h  |  34 +++
 .../armem/server/ltm/disk/MemoryManager.cpp   | 119 --------
 .../armem/server/ltm/disk/MemoryManager.h     |  39 ---
 .../armem/server/ltm/disk/ProviderSegment.cpp | 101 +++++++
 .../armem/server/ltm/disk/ProviderSegment.h   |  33 ++
 .../armem/server/ltm/disk/detail/Data.cpp     |   7 +
 .../armem/server/ltm/disk/detail/Data.h       |  65 ++++
 .../server/ltm/disk/detail/DiskStorage.cpp    |  40 +++
 .../server/ltm/disk/detail/DiskStorage.h      |  25 ++
 .../armem/server/ltm/disk/operations.cpp      | 281 ------------------
 .../armem/server/ltm/disk/operations.h        |  36 ---
 .../mongodb/ConnectionManager.cpp             |   0
 .../{ => legacy}/mongodb/ConnectionManager.h  |   0
 .../{ => legacy}/mongodb/MemoryManager.cpp    |   0
 .../ltm/{ => legacy}/mongodb/MemoryManager.h  |   2 +-
 .../ltm/{ => legacy}/mongodb/operations.cpp   |   0
 .../ltm/{ => legacy}/mongodb/operations.h     |   0
 .../libraries/armem/server/ltm/operations.cpp |  22 --
 .../libraries/armem/server/ltm/operations.h   |  13 -
 .../libraries/armem/server/plugins/Plugin.cpp |  10 +-
 .../libraries/armem/server/plugins/Plugin.h   |   1 -
 .../query_proc/base/BaseQueryProcessorBase.h  |   1 -
 .../base/CoreSegmentQueryProcessorBase.h      |  13 +-
 .../base/EntityQueryProcessorBase.h           |  61 ++--
 .../base/MemoryQueryProcessorBase.h           |  16 +-
 .../base/ProviderSegmentQueryProcessorBase.h  |  17 +-
 .../libraries/armem/server/query_proc/ltm.h   |  32 --
 .../detail/CoreSegmentQueryProcessorBase.cpp  |   1 +
 .../detail/CoreSegmentQueryProcessorBase.h    |  36 +++
 .../ltm/detail/EntityQueryProcessorBase.cpp   |   9 +
 .../ltm/detail/EntityQueryProcessorBase.h     |  35 +++
 .../ltm/detail/MemoryQueryProcessorBase.cpp   |   1 +
 .../ltm/detail/MemoryQueryProcessorBase.h     |  33 ++
 .../ProviderSegmentQueryProcessorBase.cpp     |   1 +
 .../ProviderSegmentQueryProcessorBase.h       |  33 ++
 .../armem/server/query_proc/{ => ltm}/ltm.cpp |   0
 .../armem/server/query_proc/ltm/ltm.h         |  65 ++++
 .../detail/CoreSegmentQueryProcessorBase.cpp  |   6 +
 .../wm/detail/CoreSegmentQueryProcessorBase.h |  39 +++
 .../wm/detail/EntityQueryProcessorBase.cpp    |   9 +
 .../wm/detail/EntityQueryProcessorBase.h      |  38 +++
 .../wm/detail/MemoryQueryProcessorBase.cpp    |   7 +
 .../wm/detail/MemoryQueryProcessorBase.h      |  35 +++
 .../ProviderSegmentQueryProcessorBase.cpp     |   6 +
 .../ProviderSegmentQueryProcessorBase.h       |  35 +++
 .../armem/server/query_proc/{ => wm}/wm.cpp   |   3 +-
 .../armem/server/query_proc/{ => wm}/wm.h     |  72 ++++-
 .../armem/test/ArMemLTMBenchmark.cpp          | 118 ++++++++
 .../libraries/armem/test/ArMemQueryTest.cpp   |   2 +-
 .../libraries/armem/test/CMakeLists.txt       |   1 +
 .../libraries/armem_gui/MemoryViewer.cpp      |   8 +-
 .../armem_gui/disk/ControlWidget.cpp          |  17 +-
 82 files changed, 2131 insertions(+), 862 deletions(-)
 delete mode 100644 source/RobotAPI/libraries/armem/server/ltm/LongtermMemoryBase.cpp
 delete mode 100644 source/RobotAPI/libraries/armem/server/ltm/LongtermMemoryBase.h
 create mode 100644 source/RobotAPI/libraries/armem/server/ltm/detail/BufferedMemoryBase.cpp
 create mode 100644 source/RobotAPI/libraries/armem/server/ltm/detail/BufferedMemoryBase.h
 create mode 100644 source/RobotAPI/libraries/armem/server/ltm/detail/CoreSegmentBase.cpp
 create mode 100644 source/RobotAPI/libraries/armem/server/ltm/detail/CoreSegmentBase.h
 create mode 100644 source/RobotAPI/libraries/armem/server/ltm/detail/EntityBase.cpp
 create mode 100644 source/RobotAPI/libraries/armem/server/ltm/detail/EntityBase.h
 create mode 100644 source/RobotAPI/libraries/armem/server/ltm/detail/EntitySnapshotBase.cpp
 create mode 100644 source/RobotAPI/libraries/armem/server/ltm/detail/EntitySnapshotBase.h
 create mode 100644 source/RobotAPI/libraries/armem/server/ltm/detail/LUTMemoryBase.cpp
 create mode 100644 source/RobotAPI/libraries/armem/server/ltm/detail/LUTMemoryBase.h
 create mode 100644 source/RobotAPI/libraries/armem/server/ltm/detail/MemoryBase.cpp
 create mode 100644 source/RobotAPI/libraries/armem/server/ltm/detail/MemoryBase.h
 create mode 100644 source/RobotAPI/libraries/armem/server/ltm/detail/MemoryItem.cpp
 create mode 100644 source/RobotAPI/libraries/armem/server/ltm/detail/MemoryItem.h
 create mode 100644 source/RobotAPI/libraries/armem/server/ltm/detail/ProviderSegmentBase.cpp
 create mode 100644 source/RobotAPI/libraries/armem/server/ltm/detail/ProviderSegmentBase.h
 create mode 100644 source/RobotAPI/libraries/armem/server/ltm/disk/CoreSegment.cpp
 create mode 100644 source/RobotAPI/libraries/armem/server/ltm/disk/CoreSegment.h
 create mode 100644 source/RobotAPI/libraries/armem/server/ltm/disk/Entity.cpp
 create mode 100644 source/RobotAPI/libraries/armem/server/ltm/disk/Entity.h
 create mode 100644 source/RobotAPI/libraries/armem/server/ltm/disk/EntitySnapshot.cpp
 create mode 100644 source/RobotAPI/libraries/armem/server/ltm/disk/EntitySnapshot.h
 create mode 100644 source/RobotAPI/libraries/armem/server/ltm/disk/Memory.cpp
 create mode 100644 source/RobotAPI/libraries/armem/server/ltm/disk/Memory.h
 delete mode 100644 source/RobotAPI/libraries/armem/server/ltm/disk/MemoryManager.cpp
 delete mode 100644 source/RobotAPI/libraries/armem/server/ltm/disk/MemoryManager.h
 create mode 100644 source/RobotAPI/libraries/armem/server/ltm/disk/ProviderSegment.cpp
 create mode 100644 source/RobotAPI/libraries/armem/server/ltm/disk/ProviderSegment.h
 create mode 100644 source/RobotAPI/libraries/armem/server/ltm/disk/detail/Data.cpp
 create mode 100644 source/RobotAPI/libraries/armem/server/ltm/disk/detail/Data.h
 create mode 100644 source/RobotAPI/libraries/armem/server/ltm/disk/detail/DiskStorage.cpp
 create mode 100644 source/RobotAPI/libraries/armem/server/ltm/disk/detail/DiskStorage.h
 delete mode 100644 source/RobotAPI/libraries/armem/server/ltm/disk/operations.cpp
 delete mode 100644 source/RobotAPI/libraries/armem/server/ltm/disk/operations.h
 rename source/RobotAPI/libraries/armem/server/ltm/{ => legacy}/mongodb/ConnectionManager.cpp (100%)
 rename source/RobotAPI/libraries/armem/server/ltm/{ => legacy}/mongodb/ConnectionManager.h (100%)
 rename source/RobotAPI/libraries/armem/server/ltm/{ => legacy}/mongodb/MemoryManager.cpp (100%)
 rename source/RobotAPI/libraries/armem/server/ltm/{ => legacy}/mongodb/MemoryManager.h (95%)
 rename source/RobotAPI/libraries/armem/server/ltm/{ => legacy}/mongodb/operations.cpp (100%)
 rename source/RobotAPI/libraries/armem/server/ltm/{ => legacy}/mongodb/operations.h (100%)
 delete mode 100644 source/RobotAPI/libraries/armem/server/ltm/operations.cpp
 delete mode 100644 source/RobotAPI/libraries/armem/server/ltm/operations.h
 delete mode 100644 source/RobotAPI/libraries/armem/server/query_proc/ltm.h
 create mode 100644 source/RobotAPI/libraries/armem/server/query_proc/ltm/detail/CoreSegmentQueryProcessorBase.cpp
 create mode 100644 source/RobotAPI/libraries/armem/server/query_proc/ltm/detail/CoreSegmentQueryProcessorBase.h
 create mode 100644 source/RobotAPI/libraries/armem/server/query_proc/ltm/detail/EntityQueryProcessorBase.cpp
 create mode 100644 source/RobotAPI/libraries/armem/server/query_proc/ltm/detail/EntityQueryProcessorBase.h
 create mode 100644 source/RobotAPI/libraries/armem/server/query_proc/ltm/detail/MemoryQueryProcessorBase.cpp
 create mode 100644 source/RobotAPI/libraries/armem/server/query_proc/ltm/detail/MemoryQueryProcessorBase.h
 create mode 100644 source/RobotAPI/libraries/armem/server/query_proc/ltm/detail/ProviderSegmentQueryProcessorBase.cpp
 create mode 100644 source/RobotAPI/libraries/armem/server/query_proc/ltm/detail/ProviderSegmentQueryProcessorBase.h
 rename source/RobotAPI/libraries/armem/server/query_proc/{ => ltm}/ltm.cpp (100%)
 create mode 100644 source/RobotAPI/libraries/armem/server/query_proc/ltm/ltm.h
 create mode 100644 source/RobotAPI/libraries/armem/server/query_proc/wm/detail/CoreSegmentQueryProcessorBase.cpp
 create mode 100644 source/RobotAPI/libraries/armem/server/query_proc/wm/detail/CoreSegmentQueryProcessorBase.h
 create mode 100644 source/RobotAPI/libraries/armem/server/query_proc/wm/detail/EntityQueryProcessorBase.cpp
 create mode 100644 source/RobotAPI/libraries/armem/server/query_proc/wm/detail/EntityQueryProcessorBase.h
 create mode 100644 source/RobotAPI/libraries/armem/server/query_proc/wm/detail/MemoryQueryProcessorBase.cpp
 create mode 100644 source/RobotAPI/libraries/armem/server/query_proc/wm/detail/MemoryQueryProcessorBase.h
 create mode 100644 source/RobotAPI/libraries/armem/server/query_proc/wm/detail/ProviderSegmentQueryProcessorBase.cpp
 create mode 100644 source/RobotAPI/libraries/armem/server/query_proc/wm/detail/ProviderSegmentQueryProcessorBase.h
 rename source/RobotAPI/libraries/armem/server/query_proc/{ => wm}/wm.cpp (89%)
 rename source/RobotAPI/libraries/armem/server/query_proc/{ => wm}/wm.h (54%)
 create mode 100644 source/RobotAPI/libraries/armem/test/ArMemLTMBenchmark.cpp

diff --git a/source/RobotAPI/libraries/armem/CMakeLists.txt b/source/RobotAPI/libraries/armem/CMakeLists.txt
index c589f0b3a..0f4a137d1 100644
--- a/source/RobotAPI/libraries/armem/CMakeLists.txt
+++ b/source/RobotAPI/libraries/armem/CMakeLists.txt
@@ -83,13 +83,22 @@ set(LIB_FILES
     server/MemoryRemoteGui.cpp
     server/RemoteGuiAronDataVisitor.cpp
 
-    server/ltm/operations.cpp
-    server/ltm/LongtermMemoryBase.cpp
-    server/ltm/disk/operations.cpp
-    server/ltm/disk/MemoryManager.cpp
-    server/ltm/mongodb/MemoryManager.cpp
-    server/ltm/mongodb/operations.cpp
-    server/ltm/mongodb/ConnectionManager.cpp
+    server/ltm/detail/MemoryItem.cpp
+    server/ltm/detail/MemoryBase.cpp
+    server/ltm/detail/BufferedMemoryBase.cpp
+    server/ltm/detail/LUTMemoryBase.cpp
+    server/ltm/detail/CoreSegmentBase.cpp
+    server/ltm/detail/ProviderSegmentBase.cpp
+    server/ltm/detail/EntityBase.cpp
+    server/ltm/detail/EntitySnapshotBase.cpp
+
+    server/ltm/disk/detail/Data.cpp
+    server/ltm/disk/detail/DiskStorage.cpp
+    server/ltm/disk/Memory.cpp
+    server/ltm/disk/CoreSegment.cpp
+    server/ltm/disk/ProviderSegment.cpp
+    server/ltm/disk/Entity.cpp
+    server/ltm/disk/EntitySnapshot.cpp
 
     server/wm/memory_definitions.cpp
     server/wm/ice_conversions.cpp
@@ -108,8 +117,17 @@ set(LIB_FILES
     server/query_proc/base/CoreSegmentQueryProcessorBase.cpp
     server/query_proc/base/MemoryQueryProcessorBase.cpp
 
-    server/query_proc/ltm.cpp
-    server/query_proc/wm.cpp
+    server/query_proc/ltm/detail/EntityQueryProcessorBase.cpp
+    server/query_proc/ltm/detail/ProviderSegmentQueryProcessorBase.cpp
+    server/query_proc/ltm/detail/CoreSegmentQueryProcessorBase.cpp
+    server/query_proc/ltm/detail/MemoryQueryProcessorBase.cpp
+    server/query_proc/ltm/ltm.cpp
+
+    server/query_proc/wm/detail/EntityQueryProcessorBase.cpp
+    server/query_proc/wm/detail/ProviderSegmentQueryProcessorBase.cpp
+    server/query_proc/wm/detail/CoreSegmentQueryProcessorBase.cpp
+    server/query_proc/wm/detail/MemoryQueryProcessorBase.cpp
+    server/query_proc/wm/wm.cpp
 
 
     mns/MemoryNameSystem.cpp
@@ -198,14 +216,22 @@ set(LIB_HEADERS
     server/MemoryRemoteGui.h
     server/RemoteGuiAronDataVisitor.h
 
-
-    server/ltm/operations.h
-    server/ltm/LongtermMemoryBase.h
-    server/ltm/disk/operations.h
-    server/ltm/disk/MemoryManager.h
-    server/ltm/mongodb/MemoryManager.h
-    server/ltm/mongodb/operations.h
-    server/ltm/mongodb/ConnectionManager.h
+    server/ltm/detail/MemoryItem.h
+    server/ltm/detail/MemoryBase.h
+    server/ltm/detail/BufferedMemoryBase.h
+    server/ltm/detail/LUTMemoryBase.h
+    server/ltm/detail/CoreSegmentBase.h
+    server/ltm/detail/ProviderSegmentBase.h
+    server/ltm/detail/EntityBase.h
+    server/ltm/detail/EntitySnapshotBase.h
+
+    server/ltm/disk/detail/Data.h
+    server/ltm/disk/detail/DiskStorage.h
+    server/ltm/disk/Memory.h
+    server/ltm/disk/CoreSegment.h
+    server/ltm/disk/ProviderSegment.h
+    server/ltm/disk/Entity.h
+    server/ltm/disk/EntitySnapshot.h
 
     server/wm/memory_definitions.h
     server/wm/ice_conversions.h
@@ -228,8 +254,17 @@ set(LIB_HEADERS
     server/query_proc/base/CoreSegmentQueryProcessorBase.h
     server/query_proc/base/MemoryQueryProcessorBase.h
 
-    server/query_proc/ltm.h
-    server/query_proc/wm.h
+    server/query_proc/ltm/detail/EntityQueryProcessorBase.h
+    server/query_proc/ltm/detail/ProviderSegmentQueryProcessorBase.h
+    server/query_proc/ltm/detail/CoreSegmentQueryProcessorBase.h
+    server/query_proc/ltm/detail/MemoryQueryProcessorBase.h
+    server/query_proc/ltm/ltm.h
+
+    server/query_proc/wm/detail/EntityQueryProcessorBase.h
+    server/query_proc/wm/detail/ProviderSegmentQueryProcessorBase.h
+    server/query_proc/wm/detail/CoreSegmentQueryProcessorBase.h
+    server/query_proc/wm/detail/MemoryQueryProcessorBase.h
+    server/query_proc/wm/wm.h
 
 
     mns.h
diff --git a/source/RobotAPI/libraries/armem/core/wm/aron_conversions.cpp b/source/RobotAPI/libraries/armem/core/wm/aron_conversions.cpp
index 04dadb72a..91b1a6584 100644
--- a/source/RobotAPI/libraries/armem/core/wm/aron_conversions.cpp
+++ b/source/RobotAPI/libraries/armem/core/wm/aron_conversions.cpp
@@ -5,65 +5,60 @@
 
 namespace armarx::armem
 {
-
-    constexpr const char* DATA_WRAPPER_DATA_FIELD            = "__ARON_DATA";
     constexpr const char* DATA_WRAPPER_TIME_STORED_FIELD     = "__WRITER_METADATA__TIME_STORED";
     constexpr const char* DATA_WRAPPER_TIME_CREATED_FIELD    = "__ENTITY_METADATA__TIME_CREATED";
     constexpr const char* DATA_WRAPPER_TIME_SENT_FIELD       = "__ENTITY_METADATA__TIME_SENT";
     constexpr const char* DATA_WRAPPER_TIME_ARRIVED_FIELD    = "__ENTITY_METADATA__TIME_ARRIVED";
     constexpr const char* DATA_WRAPPER_CONFIDENCE_FIELD      = "__ENTITY_METADATA__CONFIDENCE";
-
 }
 
 
-void armarx::armem::from_aron(const aron::data::DictPtr& dataWrapped, wm::EntityInstance& e)
+void armarx::armem::from_aron(const aron::data::DictPtr& metadata, const aron::data::DictPtr& data, wm::EntityInstance& e)
 {
-    wm::EntityInstanceMetadata& metadata = e.metadata();
+    ARMARX_CHECK_NOT_NULL(metadata);
+    // Todo: What if data is null?
+
+    wm::EntityInstanceMetadata& m = e.metadata();
 
-    if (dataWrapped->hasElement(DATA_WRAPPER_DATA_FIELD))
-    {
-        e.data() = aron::data::Dict::DynamicCastAndCheck(dataWrapped->getElement(DATA_WRAPPER_DATA_FIELD));
-    }
+    e.data() = data;
 
-    auto timeCreated = aron::data::Long::DynamicCastAndCheck(dataWrapped->getElement(DATA_WRAPPER_TIME_CREATED_FIELD));
-    metadata.timeCreated = Time::microSeconds(timeCreated->toAronLongPtr()->value);
+    auto timeCreated = aron::data::Long::DynamicCastAndCheck(metadata->getElement(DATA_WRAPPER_TIME_CREATED_FIELD));
+    m.timeCreated = Time::microSeconds(timeCreated->toAronLongPtr()->value);
 
-    auto timeSent = aron::data::Long::DynamicCastAndCheck(dataWrapped->getElement(DATA_WRAPPER_TIME_SENT_FIELD));
-    metadata.timeSent = Time::microSeconds(timeSent->toAronLongPtr()->value);
+    auto timeSent = aron::data::Long::DynamicCastAndCheck(metadata->getElement(DATA_WRAPPER_TIME_SENT_FIELD));
+    m.timeSent = Time::microSeconds(timeSent->toAronLongPtr()->value);
 
-    auto timeArrived = aron::data::Long::DynamicCastAndCheck(dataWrapped->getElement(DATA_WRAPPER_TIME_ARRIVED_FIELD));
-    metadata.timeArrived = Time::microSeconds(timeArrived->toAronLongPtr()->value);
+    auto timeArrived = aron::data::Long::DynamicCastAndCheck(metadata->getElement(DATA_WRAPPER_TIME_ARRIVED_FIELD));
+    m.timeArrived = Time::microSeconds(timeArrived->toAronLongPtr()->value);
 
-    auto confidence = aron::data::Double::DynamicCastAndCheck(dataWrapped->getElement(DATA_WRAPPER_CONFIDENCE_FIELD));
-    metadata.confidence = static_cast<float>(confidence->toAronDoublePtr()->value);
+    auto confidence = aron::data::Double::DynamicCastAndCheck(metadata->getElement(DATA_WRAPPER_CONFIDENCE_FIELD));
+    m.confidence = static_cast<float>(confidence->toAronDoublePtr()->value);
 }
 
 
-void armarx::armem::to_aron(aron::data::DictPtr& a, const wm::EntityInstance& e)
+void armarx::armem::to_aron(aron::data::DictPtr& metadata, aron::data::DictPtr& data, const wm::EntityInstance& e)
 {
-    if (e.data())
-    {
-        a->addElement(DATA_WRAPPER_DATA_FIELD, e.data());
-    }
+    data = e.data();
+    metadata = std::make_shared<aron::data::Dict>();
 
     auto timeWrapped = std::make_shared<aron::data::Long>();
     timeWrapped->setValue(Time::now().toMicroSeconds());
-    a->addElement(DATA_WRAPPER_TIME_STORED_FIELD, timeWrapped);
+    metadata->addElement(DATA_WRAPPER_TIME_STORED_FIELD, timeWrapped);
 
-    const wm::EntityInstanceMetadata& metadata = e.metadata();
+    const wm::EntityInstanceMetadata& m = e.metadata();
     auto timeCreated = std::make_shared<aron::data::Long>();
-    timeCreated->setValue(metadata.timeCreated.toMicroSeconds());
-    a->addElement(DATA_WRAPPER_TIME_CREATED_FIELD, timeCreated);
+    timeCreated->setValue(m.timeCreated.toMicroSeconds());
+    metadata->addElement(DATA_WRAPPER_TIME_CREATED_FIELD, timeCreated);
 
     auto timeSent = std::make_shared<aron::data::Long>();
-    timeSent->setValue(metadata.timeSent.toMicroSeconds());
-    a->addElement(DATA_WRAPPER_TIME_SENT_FIELD, timeSent);
+    timeSent->setValue(m.timeSent.toMicroSeconds());
+    metadata->addElement(DATA_WRAPPER_TIME_SENT_FIELD, timeSent);
 
     auto timeArrived = std::make_shared<aron::data::Long>();
-    timeArrived->setValue(metadata.timeArrived.toMicroSeconds());
-    a->addElement(DATA_WRAPPER_TIME_ARRIVED_FIELD, timeArrived);
+    timeArrived->setValue(m.timeArrived.toMicroSeconds());
+    metadata->addElement(DATA_WRAPPER_TIME_ARRIVED_FIELD, timeArrived);
 
     auto confidence = std::make_shared<aron::data::Double>();
-    confidence->setValue(static_cast<double>(metadata.confidence));
-    a->addElement(DATA_WRAPPER_CONFIDENCE_FIELD, confidence);
+    confidence->setValue(static_cast<double>(m.confidence));
+    metadata->addElement(DATA_WRAPPER_CONFIDENCE_FIELD, confidence);
 }
diff --git a/source/RobotAPI/libraries/armem/core/wm/aron_conversions.h b/source/RobotAPI/libraries/armem/core/wm/aron_conversions.h
index 21429da7f..d5de002ba 100644
--- a/source/RobotAPI/libraries/armem/core/wm/aron_conversions.h
+++ b/source/RobotAPI/libraries/armem/core/wm/aron_conversions.h
@@ -7,6 +7,9 @@
 
 namespace armarx::armem
 {
-    void from_aron(const aron::data::DictPtr&, wm::EntityInstance&);
-    void to_aron(aron::data::DictPtr&, const wm::EntityInstance&);
+    /// convert from metadata and data aron instance
+    void from_aron(const aron::data::DictPtr& metadata, const aron::data::DictPtr& data, wm::EntityInstance&);
+
+    /// convert to metadata and aron instance
+    void to_aron(aron::data::DictPtr& metadata, aron::data::DictPtr& data, const wm::EntityInstance&);
 }
diff --git a/source/RobotAPI/libraries/armem/server/MemoryToIceAdapter.cpp b/source/RobotAPI/libraries/armem/server/MemoryToIceAdapter.cpp
index 625d76b96..eb79ed3bf 100644
--- a/source/RobotAPI/libraries/armem/server/MemoryToIceAdapter.cpp
+++ b/source/RobotAPI/libraries/armem/server/MemoryToIceAdapter.cpp
@@ -1,7 +1,7 @@
 #include "MemoryToIceAdapter.h"
 
-#include "query_proc/wm.h"
-#include "query_proc/ltm.h"
+#include "query_proc/wm/wm.h"
+#include "query_proc/ltm/ltm.h"
 
 #include <RobotAPI/libraries/armem/server/wm/ice_conversions.h>
 
@@ -243,11 +243,8 @@ namespace armarx::armem::server
             input.withData ? armem::DataMode::WithData : armem::DataMode::NoData);
         armem::wm::Memory wmResult = wmServerProcessor.process(input.memoryQueries, *workingMemory);
 
-        armem::wm::Memory cacheAndLut = longtermMemory->getCache();
-        cacheAndLut.append(longtermMemory->getLUT());
-
-        query_proc::ltm::MemoryQueryProcessor ltmProcessor;
-        armem::wm::Memory ltmResult = ltmProcessor.process(input, cacheAndLut);
+        query_proc::ltm_server::MemoryQueryProcessor ltmProcessor;
+        armem::wm::Memory ltmResult = ltmProcessor.process(input, *longtermMemory);
 
         armem::query::data::Result result;
         if (not ltmResult.empty())
@@ -330,6 +327,7 @@ namespace armarx::armem::server
             armem::wm::Memory m;
             fromIce(queryResult.memory, m);
             longtermMemory->append(m);
+            longtermMemory->storeBuffer();
         }
 
         return output;
diff --git a/source/RobotAPI/libraries/armem/server/MemoryToIceAdapter.h b/source/RobotAPI/libraries/armem/server/MemoryToIceAdapter.h
index 7e45ab6f1..33e788ff5 100644
--- a/source/RobotAPI/libraries/armem/server/MemoryToIceAdapter.h
+++ b/source/RobotAPI/libraries/armem/server/MemoryToIceAdapter.h
@@ -4,7 +4,7 @@
 #include <RobotAPI/interface/armem/client/MemoryListenerInterface.h>
 
 #include <RobotAPI/libraries/armem/core/wm/memory_definitions.h>
-#include <RobotAPI/libraries/armem/server/ltm/disk/MemoryManager.h>
+#include <RobotAPI/libraries/armem/server/ltm/disk/Memory.h>
 #include <RobotAPI/libraries/armem/client/Query.h>
 #include <RobotAPI/libraries/armem/server/wm/memory_definitions.h>
 
diff --git a/source/RobotAPI/libraries/armem/server/ltm/LongtermMemoryBase.cpp b/source/RobotAPI/libraries/armem/server/ltm/LongtermMemoryBase.cpp
deleted file mode 100644
index 0eff25718..000000000
--- a/source/RobotAPI/libraries/armem/server/ltm/LongtermMemoryBase.cpp
+++ /dev/null
@@ -1,100 +0,0 @@
-#include "LongtermMemoryBase.h"
-
-#include <ArmarXCore/core/logging/Logging.h>
-#include <ArmarXCore/core/time/TimeUtil.h>
-
-#include <RobotAPI/libraries/armem/server/wm/memory_definitions.h>
-
-
-namespace armarx::armem::server::ltm
-{
-
-    MemoryBase::MemoryBase(const std::string& s)
-    {
-        std::lock_guard l(ltm_mutex);
-        setName(s);
-    }
-
-    void MemoryBase::setName(const std::string& name)
-    {
-        std::lock_guard l(ltm_mutex);
-        cache.name() = name;
-        lut.name() = name;
-    }
-
-
-    armem::wm::Memory MemoryBase::getCache() const
-    {
-        std::lock_guard l(ltm_mutex);
-        return cache;
-    }
-
-    armem::wm::Memory MemoryBase::getLUT() const
-    {
-        std::lock_guard l(ltm_mutex);
-        return lut;
-    }
-
-    armem::wm::Memory MemoryBase::convert()
-    {
-        std::lock_guard l(ltm_mutex);
-        armem::wm::Memory tmp = cache;
-        tmp.append(lut);
-        convert(tmp);
-        return tmp;
-    }
-
-    template <class ...Args>
-    void MemoryBase::_append(const armem::base::MemoryBase<Args...>& memory)
-    {
-        TIMING_START(LTM_Append);
-        ARMARX_INFO << "Append memory with name '" << memory.name() << "' into the cache of the LTM with name '" << cache.name() << "'";
-
-        std::lock_guard l(ltm_mutex);
-        cache.append(memory);
-
-        TIMING_END_STREAM(LTM_Append, ARMARX_DEBUG);
-    }
-
-
-    void MemoryBase::append(const armem::wm::Memory& memory)
-    {
-        this->_append(memory);
-    }
-
-
-    void MemoryBase::append(const armem::server::wm::Memory& memory)
-    {
-        this->_append(memory);
-    }
-
-    void MemoryBase::moveCacheToLUTAndClearCache()
-    {
-        cache.forEachInstance([](armem::wm::EntityInstance & i)
-        {
-            i.data() = nullptr;
-        });
-
-        lut.append(cache);
-        cache.clear();
-    }
-
-    void MemoryBase::checkUpdateLatestSnapshot(const armem::wm::EntitySnapshot& newSnapshot)
-    {
-        if (auto it = latestSnapshots.find(newSnapshot.id().getEntityID()); it != latestSnapshots.end())
-        {
-            auto& ptr = it->second;
-            if (ptr->id().timestamp < newSnapshot.id().timestamp)
-            {
-                ptr = &newSnapshot;
-            }
-            // else ignore ==> no update
-        }
-        else
-        {
-            // no entry yet
-            latestSnapshots.emplace(newSnapshot.id().getEntityID().str(), &newSnapshot);
-        }
-    }
-
-} // namespace armarx::armem::server::ltm
diff --git a/source/RobotAPI/libraries/armem/server/ltm/LongtermMemoryBase.h b/source/RobotAPI/libraries/armem/server/ltm/LongtermMemoryBase.h
deleted file mode 100644
index 0514eec76..000000000
--- a/source/RobotAPI/libraries/armem/server/ltm/LongtermMemoryBase.h
+++ /dev/null
@@ -1,69 +0,0 @@
-#pragma once
-
-#include <map>
-#include <mutex>
-#include <optional>
-#include <string>
-
-#include <RobotAPI/libraries/armem/core/MemoryID.h>
-#include <RobotAPI/libraries/armem/core/wm/memory_definitions.h>
-#include <RobotAPI/libraries/armem/server/forward_declarations.h>
-
-
-namespace armarx::armem::server::ltm
-{
-    /// @brief Interface functions for the longterm memory classes
-    class MemoryBase
-    {
-    public:
-        MemoryBase() = default;
-        MemoryBase(const std::string&);
-
-        void append(const armem::wm::Memory& memory);
-        void append(const armem::server::wm::Memory& memory);
-
-        /// reload the lut content from the long-term memory
-        virtual void reload() = 0;
-
-        /// convert the references of the input into a wm::Memory
-        virtual void convert(armem::wm::Memory&) = 0;
-
-        /// convert the references of the cache and the LUT into a wm::Memory
-        armem::wm::Memory convert();
-
-        /// encode the content in the cache and store it in the long-term memory
-        virtual void encodeAndStore() = 0;
-
-        /// set the name of this memory
-        void setName(const std::string& name);
-
-        armem::wm::Memory getCache() const;
-        armem::wm::Memory getLUT() const;
-
-    protected:
-        void moveCacheToLUTAndClearCache();
-        void checkUpdateLatestSnapshot(const armem::wm::EntitySnapshot& newSnapshot);
-
-    protected:
-        mutable std::recursive_mutex ltm_mutex;
-
-        /// Internal memory for data consolidated from wm to ltm (cache)
-        /// The to-put-to-ltm cache (contains data in plain text)
-        armem::wm::Memory cache;
-
-        /// Internal memory for indexes (lut)
-        /// It contains indexes to all memory entries (TODO!)
-        armem::wm::Memory lut;
-
-        /// A map from entityID to its latest snapshot stored.
-        /// When adding a new snapshot we compare it to the last one stored without querying the long-term memory
-        std::map<MemoryID, const armem::wm::EntitySnapshot*> latestSnapshots;
-
-
-    private:
-
-        template <class ...Args>
-        void _append(const armem::base::MemoryBase<Args...>& memory);
-
-    };
-} // namespace armarx::armem::server::ltm
diff --git a/source/RobotAPI/libraries/armem/server/ltm/detail/BufferedMemoryBase.cpp b/source/RobotAPI/libraries/armem/server/ltm/detail/BufferedMemoryBase.cpp
new file mode 100644
index 000000000..864266ce8
--- /dev/null
+++ b/source/RobotAPI/libraries/armem/server/ltm/detail/BufferedMemoryBase.cpp
@@ -0,0 +1,7 @@
+#include "BufferedMemoryBase.h"
+
+namespace armarx::armem::server::ltm
+{
+
+
+} // namespace armarx::armem::server::ltm
diff --git a/source/RobotAPI/libraries/armem/server/ltm/detail/BufferedMemoryBase.h b/source/RobotAPI/libraries/armem/server/ltm/detail/BufferedMemoryBase.h
new file mode 100644
index 000000000..aabceb4c0
--- /dev/null
+++ b/source/RobotAPI/libraries/armem/server/ltm/detail/BufferedMemoryBase.h
@@ -0,0 +1,45 @@
+#pragma once
+
+#include "MemoryBase.h"
+
+namespace armarx::armem::server::ltm
+{
+    template <class _CoreSegmentT>
+    class BufferedMemoryBase : virtual public MemoryBase<_CoreSegmentT>
+    {
+    public:
+        using MemoryBase<_CoreSegmentT>::MemoryBase;
+        BufferedMemoryBase(const MemoryID&) = delete; // remove non-default constructor
+
+        armem::wm::Memory getBuffer() const
+        {
+            std::lock_guard l(this->ltm_mutex);
+            return buffer;
+        }
+
+        void storeBuffer()
+        {
+            this->store(buffer);
+            buffer.clear();
+        }
+
+        void setMemoryID(const MemoryID& id) override
+        {
+            MemoryBase<_CoreSegmentT>::setMemoryID(id);
+            buffer.name() = this->name();
+        }
+
+        void append(const armem::wm::Memory& memory) override
+        {
+            std::lock_guard l(this->ltm_mutex);
+            buffer.append(memory);
+        }
+
+    protected:
+
+        /// Internal memory for data consolidated from wm to ltm (buffer)
+        /// The to-put-to-ltm buffer (contains data in plain text)
+        armem::wm::Memory buffer;
+
+    };
+} // namespace armarx::armem::server::ltm
diff --git a/source/RobotAPI/libraries/armem/server/ltm/detail/CoreSegmentBase.cpp b/source/RobotAPI/libraries/armem/server/ltm/detail/CoreSegmentBase.cpp
new file mode 100644
index 000000000..cdeac5414
--- /dev/null
+++ b/source/RobotAPI/libraries/armem/server/ltm/detail/CoreSegmentBase.cpp
@@ -0,0 +1,6 @@
+#include "CoreSegmentBase.h"
+
+namespace armarx::armem::server::ltm
+{
+
+} // namespace armarx::armem::server::ltm
diff --git a/source/RobotAPI/libraries/armem/server/ltm/detail/CoreSegmentBase.h b/source/RobotAPI/libraries/armem/server/ltm/detail/CoreSegmentBase.h
new file mode 100644
index 000000000..807d45f20
--- /dev/null
+++ b/source/RobotAPI/libraries/armem/server/ltm/detail/CoreSegmentBase.h
@@ -0,0 +1,56 @@
+#pragma once
+
+#include <functional>
+
+// BaseClass
+#include "MemoryItem.h"
+
+#include "ProviderSegmentBase.h"
+
+#include <RobotAPI/libraries/armem/core/MemoryID.h>
+#include <RobotAPI/libraries/armem/core/wm/memory_definitions.h>
+#include <RobotAPI/libraries/armem/core/wm/aron_conversions.h>
+
+namespace armarx::armem::server::ltm
+{
+    /// @brief Interface functions for the longterm memory classes
+    template <class _ProviderSegmentT>
+    class CoreSegmentBase : public MemoryItem
+    {
+    public:
+        using ProviderSegmentT = _ProviderSegmentT;
+
+        using MemoryItem::MemoryItem;
+
+        /// return the full sub-ltm as a wm::CoreSegment with only references
+        /// the ltm may be huge, use with caution
+        virtual armem::wm::CoreSegment loadAll() = 0;
+
+        /// convert the references of the input into a wm::Memory
+        virtual void convert(armem::wm::CoreSegment&) = 0;
+
+        /// encode the content of a wm::Memory and store
+        virtual void store(const armem::wm::CoreSegment&) = 0;
+
+        /// iterate over all provider segments of this ltm
+        virtual bool forEachProviderSegment(std::function<void(ProviderSegmentT&)>&& func) const = 0;
+
+        /// find provider segment
+        virtual std::shared_ptr<ProviderSegmentT> findProviderSegment(const std::string&) const = 0;
+
+        /// get aron type
+        aron::type::ObjectPtr aronType() const
+        {
+            return nullptr;
+        }
+
+        /// get level name
+        static std::string getLevelName()
+        {
+            return "LT-CoreSegment";
+        }
+
+    protected:
+        mutable std::recursive_mutex ltm_mutex;
+    };
+} // namespace armarx::armem::server::ltm
diff --git a/source/RobotAPI/libraries/armem/server/ltm/detail/EntityBase.cpp b/source/RobotAPI/libraries/armem/server/ltm/detail/EntityBase.cpp
new file mode 100644
index 000000000..a0f93fc47
--- /dev/null
+++ b/source/RobotAPI/libraries/armem/server/ltm/detail/EntityBase.cpp
@@ -0,0 +1,10 @@
+#include "EntityBase.h"
+
+#include <ArmarXCore/core/logging/Logging.h>
+#include <ArmarXCore/core/time/TimeUtil.h>
+
+#include <RobotAPI/libraries/armem/server/wm/memory_definitions.h>
+
+namespace armarx::armem::server::ltm
+{
+} // namespace armarx::armem::server::ltm
diff --git a/source/RobotAPI/libraries/armem/server/ltm/detail/EntityBase.h b/source/RobotAPI/libraries/armem/server/ltm/detail/EntityBase.h
new file mode 100644
index 000000000..49dcbbee0
--- /dev/null
+++ b/source/RobotAPI/libraries/armem/server/ltm/detail/EntityBase.h
@@ -0,0 +1,58 @@
+#pragma once
+
+#include <functional>
+
+// BaseClass
+#include "MemoryItem.h"
+
+#include "EntitySnapshotBase.h"
+
+#include <RobotAPI/libraries/armem/core/MemoryID.h>
+#include <RobotAPI/libraries/armem/core/wm/memory_definitions.h>
+#include <RobotAPI/libraries/armem/core/wm/aron_conversions.h>
+
+namespace armarx::armem::server::ltm
+{
+    /// @brief Interface functions for the longterm memory classes
+    template <class _EntitySnapshotT>
+    class EntityBase : public MemoryItem
+    {
+    public:
+        using EntitySnapshotT = _EntitySnapshotT;
+
+        using MemoryItem::MemoryItem;
+
+        /// return the full sub-ltm as a wm::Entity with only references
+        /// the ltm may be huge, use with caution
+        virtual armem::wm::Entity loadAll() = 0;
+
+        /// convert the references of the input into a wm::Memory
+        virtual void convert(armem::wm::Entity&) = 0;
+
+        /// encode the content of a wm::Memory and store
+        virtual void store(const armem::wm::Entity&) = 0;
+
+        /// iterate over all entity snapshots of this ltm
+        virtual bool forEachSnapshot(std::function<void(EntitySnapshotT&)>&& func) const = 0;
+        virtual bool forEachSnapshotInIndexRange(long first, long last, std::function<void(EntitySnapshotT&)>&& func) const = 0;
+        virtual bool forEachSnapshotInTimeRange(const Time& min, const Time& max, std::function<void(EntitySnapshotT&)>&& func) const = 0;
+        virtual bool forEachSnapshotBeforeOrAt(const Time& time, std::function<void(EntitySnapshotT&)>&& func) const = 0;
+        virtual bool forEachSnapshotBefore(const Time& time, std::function<void(EntitySnapshotT&)>&& func) const = 0;
+
+        /// find entity snapshot segment
+        virtual std::shared_ptr<EntitySnapshotT> findSnapshot(const Time&) const = 0;
+        virtual std::shared_ptr<EntitySnapshotT> findLatestSnapshot() const = 0;
+        virtual std::shared_ptr<EntitySnapshotT> findLatestSnapshotBefore(const Time& time) const = 0;
+        virtual std::shared_ptr<EntitySnapshotT> findLatestSnapshotBeforeOrAt(const Time& time) const = 0;
+        virtual std::shared_ptr<EntitySnapshotT> findFirstSnapshotAfter(const Time& time) const = 0;
+        virtual std::shared_ptr<EntitySnapshotT> findFirstSnapshotAfterOrAt(const Time& time) const = 0;
+
+        static std::string getLevelName()
+        {
+            return "LT-Entity";
+        }
+
+    protected:
+        mutable std::recursive_mutex ltm_mutex;
+    };
+} // namespace armarx::armem::server::ltm
diff --git a/source/RobotAPI/libraries/armem/server/ltm/detail/EntitySnapshotBase.cpp b/source/RobotAPI/libraries/armem/server/ltm/detail/EntitySnapshotBase.cpp
new file mode 100644
index 000000000..1b053d008
--- /dev/null
+++ b/source/RobotAPI/libraries/armem/server/ltm/detail/EntitySnapshotBase.cpp
@@ -0,0 +1,14 @@
+#include "EntitySnapshotBase.h"
+
+#include <ArmarXCore/core/logging/Logging.h>
+#include <ArmarXCore/core/time/TimeUtil.h>
+
+#include <RobotAPI/libraries/armem/server/wm/memory_definitions.h>
+
+namespace armarx::armem::server::ltm
+{
+    std::string EntitySnapshotBase::getLevelName()
+    {
+        return "LT-EntitySnapshot";
+    }
+} // namespace armarx::armem::server::ltm
diff --git a/source/RobotAPI/libraries/armem/server/ltm/detail/EntitySnapshotBase.h b/source/RobotAPI/libraries/armem/server/ltm/detail/EntitySnapshotBase.h
new file mode 100644
index 000000000..027ac262f
--- /dev/null
+++ b/source/RobotAPI/libraries/armem/server/ltm/detail/EntitySnapshotBase.h
@@ -0,0 +1,36 @@
+#pragma once
+
+#include <functional>
+
+// BaseClass
+#include "MemoryItem.h"
+
+#include <RobotAPI/libraries/armem/core/MemoryID.h>
+#include <RobotAPI/libraries/armem/core/wm/memory_definitions.h>
+#include <RobotAPI/libraries/armem/core/wm/aron_conversions.h>
+
+namespace armarx::armem::server::ltm
+{
+    /// @brief Interface functions for the longterm memory classes
+    class EntitySnapshotBase : public MemoryItem
+    {
+    public:
+
+        using MemoryItem::MemoryItem;
+
+        /// return the full sub-ltm as a wm::EntitySnapshot with only references
+        /// the ltm may be huge, use with caution
+        virtual armem::wm::EntitySnapshot loadAll() const = 0;
+
+        /// convert the references of the input into a wm::Memory
+        virtual void convert(armem::wm::EntitySnapshot&) const = 0;
+
+        /// encode the content of a wm::Memory and store
+        virtual void store(const armem::wm::EntitySnapshot&) const = 0;
+
+        static std::string getLevelName();
+
+    protected:
+        mutable std::recursive_mutex ltm_mutex;
+    };
+} // namespace armarx::armem::server::ltm
diff --git a/source/RobotAPI/libraries/armem/server/ltm/detail/LUTMemoryBase.cpp b/source/RobotAPI/libraries/armem/server/ltm/detail/LUTMemoryBase.cpp
new file mode 100644
index 000000000..1078e776d
--- /dev/null
+++ b/source/RobotAPI/libraries/armem/server/ltm/detail/LUTMemoryBase.cpp
@@ -0,0 +1,6 @@
+#include "LUTMemoryBase.h"
+
+namespace armarx::armem::server::ltm
+{
+
+} // namespace armarx::armem::server::ltm
diff --git a/source/RobotAPI/libraries/armem/server/ltm/detail/LUTMemoryBase.h b/source/RobotAPI/libraries/armem/server/ltm/detail/LUTMemoryBase.h
new file mode 100644
index 000000000..49d05ab2b
--- /dev/null
+++ b/source/RobotAPI/libraries/armem/server/ltm/detail/LUTMemoryBase.h
@@ -0,0 +1,47 @@
+#pragma once
+
+#include "MemoryBase.h"
+
+namespace armarx::armem::server::ltm
+{
+    template <class _CoreSegmentT>
+    class LUTMemoryBase : virtual public MemoryBase<_CoreSegmentT>
+    {
+    public:
+        using MemoryBase<_CoreSegmentT>::MemoryBase;
+
+        armem::wm::Memory getLUT() const
+        {
+            std::lock_guard l(this->ltm_mutex);
+            return lut;
+        }
+
+        void setMemoryID(const MemoryID& id) override
+        {
+            MemoryBase<_CoreSegmentT>::setMemoryID(id);
+            lut.name() = this->name();
+        }
+
+    protected:
+        static bool EntitySnapshotHasData(const armem::wm::EntitySnapshot& e)
+        {
+            // check whether all data is nullptr
+            bool allDataIsNull = e.size() > 0;
+            e.forEachInstance([&allDataIsNull](armem::wm::EntityInstance & e)
+            {
+                if (e.data())
+                {
+                    allDataIsNull = false;
+                    return false; // means break
+                }
+                return true;
+            });
+            return !allDataIsNull;
+        }
+
+    protected:
+
+        armem::wm::Memory lut;
+
+    };
+} // namespace armarx::armem::server::ltm
diff --git a/source/RobotAPI/libraries/armem/server/ltm/detail/MemoryBase.cpp b/source/RobotAPI/libraries/armem/server/ltm/detail/MemoryBase.cpp
new file mode 100644
index 000000000..3375b372d
--- /dev/null
+++ b/source/RobotAPI/libraries/armem/server/ltm/detail/MemoryBase.cpp
@@ -0,0 +1,6 @@
+#include "MemoryBase.h"
+
+namespace armarx::armem::server::ltm
+{
+
+} // namespace armarx::armem::server::ltm
diff --git a/source/RobotAPI/libraries/armem/server/ltm/detail/MemoryBase.h b/source/RobotAPI/libraries/armem/server/ltm/detail/MemoryBase.h
new file mode 100644
index 000000000..919619488
--- /dev/null
+++ b/source/RobotAPI/libraries/armem/server/ltm/detail/MemoryBase.h
@@ -0,0 +1,55 @@
+#pragma once
+
+#include <functional>
+
+// BaseClass
+#include "MemoryItem.h"
+
+#include "CoreSegmentBase.h"
+
+#include <RobotAPI/libraries/armem/core/MemoryID.h>
+#include <RobotAPI/libraries/armem/core/wm/memory_definitions.h>
+#include <RobotAPI/libraries/armem/core/wm/aron_conversions.h>
+
+namespace armarx::armem::server::ltm
+{
+    /// @brief Interface functions for the longterm memory classes
+    template <class _CoreSegmentT>
+    class MemoryBase : public MemoryItem
+    {
+    public:
+        using CoreSegmentT = _CoreSegmentT;
+
+        using MemoryItem::MemoryItem;
+
+        /// return the full ltm as a wm::Memory with only references
+        /// the ltm may be huge, use with caution
+        virtual armem::wm::Memory loadAll() = 0;
+
+        /// append a wm::Memory instance to the ltm
+        virtual void append(const armem::wm::Memory& memory) = 0;
+
+        /// convert the references of the input into a wm::Memory
+        virtual void convert(armem::wm::Memory&) = 0;
+
+        /// encode the content of a wm::Memory and store
+        virtual void store(const armem::wm::Memory&) = 0;
+
+        /// iterate over all core segments of this ltm
+        virtual bool forEachCoreSegment(std::function<void(CoreSegmentT&)>&& func) const = 0;
+
+        /// find core segment
+        virtual std::shared_ptr<CoreSegmentT> findCoreSegment(const std::string&) const = 0;
+
+        /// get level name
+        static std::string getLevelName()
+        {
+            return "LT-Memory";
+        }
+
+    protected:
+        mutable std::recursive_mutex ltm_mutex;
+
+
+    };
+} // namespace armarx::armem::server::ltm
diff --git a/source/RobotAPI/libraries/armem/server/ltm/detail/MemoryItem.cpp b/source/RobotAPI/libraries/armem/server/ltm/detail/MemoryItem.cpp
new file mode 100644
index 000000000..0187962b3
--- /dev/null
+++ b/source/RobotAPI/libraries/armem/server/ltm/detail/MemoryItem.cpp
@@ -0,0 +1,28 @@
+#include "MemoryItem.h"
+
+#include <ArmarXCore/core/logging/Logging.h>
+#include <ArmarXCore/core/time/TimeUtil.h>
+
+#include <RobotAPI/libraries/armem/server/wm/memory_definitions.h>
+
+namespace armarx::armem::server::ltm
+{
+    MemoryItem::MemoryItem(const MemoryID& id) : _id(id)
+    {
+    }
+
+    void MemoryItem::setMemoryID(const MemoryID& id)
+    {
+        _id = id;
+    }
+
+    MemoryID MemoryItem::id() const
+    {
+        return _id;
+    }
+
+    std::string MemoryItem::name() const
+    {
+        return _id.getLeafItem();
+    }
+} // namespace armarx::armem::server::ltm
diff --git a/source/RobotAPI/libraries/armem/server/ltm/detail/MemoryItem.h b/source/RobotAPI/libraries/armem/server/ltm/detail/MemoryItem.h
new file mode 100644
index 000000000..7309bbd59
--- /dev/null
+++ b/source/RobotAPI/libraries/armem/server/ltm/detail/MemoryItem.h
@@ -0,0 +1,27 @@
+#pragma once
+
+#include <map>
+#include <mutex>
+#include <optional>
+#include <string>
+
+#include <RobotAPI/libraries/armem/core/MemoryID.h>
+
+namespace armarx::armem::server::ltm
+{
+    /// @brief Interface functions for the longterm memory classes
+    class MemoryItem
+    {
+    public:
+        MemoryItem() = default;
+        MemoryItem(const MemoryID&);
+
+        MemoryID id() const;
+        std::string name() const;
+
+        virtual void setMemoryID(const MemoryID&);
+
+    private:
+        MemoryID _id;
+    };
+} // namespace armarx::armem::server::ltm
diff --git a/source/RobotAPI/libraries/armem/server/ltm/detail/ProviderSegmentBase.cpp b/source/RobotAPI/libraries/armem/server/ltm/detail/ProviderSegmentBase.cpp
new file mode 100644
index 000000000..15a2cc306
--- /dev/null
+++ b/source/RobotAPI/libraries/armem/server/ltm/detail/ProviderSegmentBase.cpp
@@ -0,0 +1,11 @@
+#include "ProviderSegmentBase.h"
+
+#include <ArmarXCore/core/logging/Logging.h>
+#include <ArmarXCore/core/time/TimeUtil.h>
+
+#include <RobotAPI/libraries/armem/server/wm/memory_definitions.h>
+
+namespace armarx::armem::server::ltm
+{
+
+} // namespace armarx::armem::server::ltm
diff --git a/source/RobotAPI/libraries/armem/server/ltm/detail/ProviderSegmentBase.h b/source/RobotAPI/libraries/armem/server/ltm/detail/ProviderSegmentBase.h
new file mode 100644
index 000000000..9294a6c19
--- /dev/null
+++ b/source/RobotAPI/libraries/armem/server/ltm/detail/ProviderSegmentBase.h
@@ -0,0 +1,56 @@
+#pragma once
+
+#include <functional>
+
+// BaseClass
+#include "MemoryItem.h"
+
+#include "EntityBase.h"
+
+#include <RobotAPI/libraries/armem/core/MemoryID.h>
+#include <RobotAPI/libraries/armem/core/wm/memory_definitions.h>
+#include <RobotAPI/libraries/armem/core/wm/aron_conversions.h>
+
+namespace armarx::armem::server::ltm
+{
+    /// @brief Interface functions for the longterm memory classes
+    template <class _EntityT>
+    class ProviderSegmentBase : public MemoryItem
+    {
+    public:
+        using EntityT = _EntityT;
+
+        using MemoryItem::MemoryItem;
+
+        /// return the full sub-ltm as a wm::ProviderSegment with only references
+        /// the ltm may be huge, use with caution
+        virtual armem::wm::ProviderSegment loadAll() = 0;
+
+        /// convert the references of the input into a wm::Memory
+        virtual void convert(armem::wm::ProviderSegment&) = 0;
+
+        /// encode the content of a wm::Memory and store
+        virtual void store(const armem::wm::ProviderSegment&) = 0;
+
+        /// iterate over all core segments of this ltm
+        virtual bool forEachEntity(std::function<void(EntityT&)>&& func) const = 0;
+
+        /// find entity segment
+        virtual std::shared_ptr<EntityT> findEntity(const std::string&) const = 0;
+
+        aron::type::ObjectPtr aronType() const
+        {
+            return nullptr;
+        }
+
+        static std::string getLevelName()
+        {
+            return "LT-ProviderSegment";
+        }
+
+    protected:
+
+    protected:
+        mutable std::recursive_mutex ltm_mutex;
+    };
+} // namespace armarx::armem::server::ltm
diff --git a/source/RobotAPI/libraries/armem/server/ltm/disk/CoreSegment.cpp b/source/RobotAPI/libraries/armem/server/ltm/disk/CoreSegment.cpp
new file mode 100644
index 000000000..5de81875d
--- /dev/null
+++ b/source/RobotAPI/libraries/armem/server/ltm/disk/CoreSegment.cpp
@@ -0,0 +1,100 @@
+// Header
+#include "CoreSegment.h"
+
+// ArmarX
+#include <ArmarXCore/core/time/TimeUtil.h>
+#include <ArmarXCore/core/logging/Logging.h>
+
+namespace armarx::armem::server::ltm::disk
+{
+    namespace
+    {
+        MemoryID getMemoryIDFromPath(const std::filesystem::path& p)
+        {
+            util::ensureFolderExists(p);
+
+            MemoryID m;
+            m.memoryName = p.parent_path().filename();
+            m.coreSegmentName = p.filename();
+            return m;
+        }
+    }
+
+    CoreSegment::CoreSegment(const std::filesystem::path& p) :
+        CoreSegmentBase(getMemoryIDFromPath(p)),
+        DiskStorage(p)
+    {
+    }
+
+    bool CoreSegment::forEachProviderSegment(std::function<void(ProviderSegment&)>&& func) const
+    {
+        if (!checkPath())
+        {
+            return false;
+        }
+
+        std::filesystem::path p = path;
+        util::ensureFolderExists(p, false);
+
+        for (const auto& subdir : std::filesystem::directory_iterator(p))
+        {
+            std::filesystem::path subdirPath = subdir.path();
+            ProviderSegment c(subdirPath);
+            func(c);
+        }
+        return true;
+    }
+
+    std::shared_ptr<ProviderSegment> CoreSegment::findProviderSegment(const std::string& n) const
+    {
+        if (!checkPath())
+        {
+            return {};
+        }
+
+        std::filesystem::path p = path;
+        util::ensureFolderExists(p, false);
+
+        std::filesystem::path subpath = p / n;
+        util::ensureFolderExists(subpath, false);
+        auto c = std::make_shared<ProviderSegment>(subpath);
+        return c;
+    }
+
+    std::string CoreSegment::getExpectedFolderName() const
+    {
+        return name();
+    }
+
+    armem::wm::CoreSegment CoreSegment::loadAll()
+    {
+        armem::wm::CoreSegment e(id());
+
+        forEachProviderSegment([&e](ProviderSegment& x) {
+            auto s = x.loadAll();
+            e.addProviderSegment(s);
+        });
+
+        return e;
+    }
+
+    void CoreSegment::convert(armem::wm::CoreSegment& c)
+    {
+        c.forEachProviderSegment([this](armem::wm::ProviderSegment& e)
+        {
+            util::ensureFolderExists(std::filesystem::path(path) / e.id().providerSegmentName, false);
+            ProviderSegment c(std::filesystem::path(path) / e.id().providerSegmentName);
+            c.convert(e);
+        });
+    }
+
+    void CoreSegment::store(const armem::wm::CoreSegment& c)
+    {
+        c.forEachProviderSegment([this](const armem::wm::ProviderSegment& e)
+        {
+            util::ensureFolderExists(std::filesystem::path(path) / e.id().providerSegmentName);
+            ProviderSegment c(std::filesystem::path(path) / e.id().providerSegmentName);
+            c.store(e);
+        });
+    }
+}
diff --git a/source/RobotAPI/libraries/armem/server/ltm/disk/CoreSegment.h b/source/RobotAPI/libraries/armem/server/ltm/disk/CoreSegment.h
new file mode 100644
index 000000000..1ec95bd79
--- /dev/null
+++ b/source/RobotAPI/libraries/armem/server/ltm/disk/CoreSegment.h
@@ -0,0 +1,33 @@
+#pragma once
+
+#include <filesystem>
+
+// Base Class
+#include "../detail/CoreSegmentBase.h"
+#include "detail/DiskStorage.h"
+
+#include "ProviderSegment.h"
+
+namespace armarx::armem::server::ltm::disk
+{
+    class CoreSegment :
+            public CoreSegmentBase<ProviderSegment>,
+            public DiskStorage
+    {
+    public:
+        using CoreSegmentBase::CoreSegmentBase;
+        CoreSegment(const std::filesystem::path&);
+
+        armem::wm::CoreSegment loadAll() override;
+        void convert(armem::wm::CoreSegment&) override;
+        void store(const armem::wm::CoreSegment&) override;
+
+        bool forEachProviderSegment(std::function<void(ProviderSegment&)>&& func) const override;
+
+        std::shared_ptr<ProviderSegment> findProviderSegment(const std::string&) const override;
+
+    protected:
+        std::string getExpectedFolderName() const override;
+    };
+
+} // namespace armarx::armem::server::ltm::disk
diff --git a/source/RobotAPI/libraries/armem/server/ltm/disk/Entity.cpp b/source/RobotAPI/libraries/armem/server/ltm/disk/Entity.cpp
new file mode 100644
index 000000000..5ddabc38e
--- /dev/null
+++ b/source/RobotAPI/libraries/armem/server/ltm/disk/Entity.cpp
@@ -0,0 +1,148 @@
+// Header
+#include "Entity.h"
+
+// ArmarX
+#include <ArmarXCore/core/time/TimeUtil.h>
+#include <ArmarXCore/core/logging/Logging.h>
+
+namespace armarx::armem::server::ltm::disk
+{
+
+    namespace
+    {
+        MemoryID getMemoryIDFromPath(const std::filesystem::path& p)
+        {
+            util::ensureFolderExists(p);
+
+            MemoryID m;
+            m.memoryName = p.parent_path().parent_path().parent_path().filename();
+            m.coreSegmentName = p.parent_path().parent_path().filename();
+            m.providerSegmentName = p.parent_path().filename();
+            m.entityName = p.filename();
+            return m;
+        }
+    }
+
+    Entity::Entity(const std::filesystem::path& p) :
+        EntityBase(getMemoryIDFromPath(p)),
+        DiskStorage(p)
+    {
+    }
+
+    std::string Entity::getExpectedFolderName() const
+    {
+        return name();
+    }
+
+    bool Entity::forEachSnapshot(std::function<void(EntitySnapshot&)>&& func) const
+    {
+        if (!checkPath())
+        {
+            return false;
+        }
+
+        std::filesystem::path p = path;
+        util::ensureFolderExists(p, false);
+
+        for (const auto& subdir : std::filesystem::directory_iterator(p))
+        {
+            std::filesystem::path subdirPath = subdir.path();
+            EntitySnapshot c(subdirPath);
+            func(c);
+        }
+        return true;
+    }
+
+    bool Entity::forEachSnapshotInIndexRange(long first, long last, std::function<void(EntitySnapshot&)>&& func) const
+    {
+        return true;
+    }
+
+    bool Entity::forEachSnapshotInTimeRange(const Time& min, const Time& max, std::function<void(EntitySnapshot&)>&& func) const
+    {
+        return true;
+    }
+
+    bool Entity::forEachSnapshotBeforeOrAt(const Time& time, std::function<void(EntitySnapshot&)>&& func) const
+    {
+        return true;
+    }
+
+    bool Entity::forEachSnapshotBefore(const Time& time, std::function<void(EntitySnapshot&)>&& func) const
+    {
+        return true;
+    }
+
+    std::shared_ptr<EntitySnapshot> Entity::findSnapshot(const Time& n) const
+    {
+        if (!checkPath())
+        {
+            return {};
+        }
+
+        std::filesystem::path p = path;
+        util::ensureFolderExists(p, false);
+
+        std::filesystem::path subpath = p / std::to_string(n.toMicroSeconds());
+        util::ensureFolderExists(subpath, false);
+        auto c = std::make_shared<EntitySnapshot>(subpath);
+        return c;
+    }
+
+    std::shared_ptr<EntitySnapshot> Entity::findLatestSnapshot() const
+    {
+        return {};
+    }
+
+    std::shared_ptr<EntitySnapshot> Entity::findLatestSnapshotBefore(const Time& time) const
+    {
+        return {};
+    }
+
+    std::shared_ptr<EntitySnapshot> Entity::findLatestSnapshotBeforeOrAt(const Time& time) const
+    {
+        return {};
+    }
+
+    std::shared_ptr<EntitySnapshot> Entity::findFirstSnapshotAfter(const Time& time) const
+    {
+        return {};
+    }
+
+    std::shared_ptr<EntitySnapshot> Entity::findFirstSnapshotAfterOrAt(const Time& time) const
+    {
+        return {};
+    }
+
+    armem::wm::Entity Entity::loadAll()
+    {
+        armem::wm::Entity e(id());
+
+        forEachSnapshot([&e](EntitySnapshotBase& x) {
+            auto s = x.loadAll();
+            e.addSnapshot(s);
+        });
+
+        return e;
+    }
+
+    void Entity::convert(armem::wm::Entity& p)
+    {
+        p.forEachSnapshot([this](armem::wm::EntitySnapshot& e)
+        {
+            util::ensureFolderExists(std::filesystem::path(path) / std::to_string(e.id().timestamp.toMicroSeconds()), false);
+            EntitySnapshot c(std::filesystem::path(path) / std::to_string(e.id().timestamp.toMicroSeconds()));
+            c.store(e);
+        });
+    }
+
+    void Entity::store(const armem::wm::Entity& c)
+    {
+        c.forEachSnapshot([this](armem::wm::EntitySnapshot& e)
+        {
+            util::ensureFolderExists(std::filesystem::path(path) / std::to_string(e.id().timestamp.toMicroSeconds()));
+            EntitySnapshot c(std::filesystem::path(path) / std::to_string(e.id().timestamp.toMicroSeconds()));
+            c.store(e);
+        });
+    }
+}
diff --git a/source/RobotAPI/libraries/armem/server/ltm/disk/Entity.h b/source/RobotAPI/libraries/armem/server/ltm/disk/Entity.h
new file mode 100644
index 000000000..3d0aacfb3
--- /dev/null
+++ b/source/RobotAPI/libraries/armem/server/ltm/disk/Entity.h
@@ -0,0 +1,43 @@
+#pragma once
+
+#include <filesystem>
+
+// Base Class
+#include "../detail/EntityBase.h"
+#include "detail/DiskStorage.h"
+
+#include "EntitySnapshot.h"
+
+namespace armarx::armem::server::ltm::disk
+{
+    /// @brief A memory storing data in mongodb (needs 'armarx memory start' to start the mongod instance)
+    class Entity :
+            public EntityBase<EntitySnapshot>,
+            public DiskStorage
+    {
+    public:
+        using EntityBase::EntityBase;
+        Entity(const std::filesystem::path&);
+
+        armem::wm::Entity loadAll() override;
+        void convert(armem::wm::Entity&) override;
+        void store(const armem::wm::Entity&) override;
+
+        bool forEachSnapshot(std::function<void(EntitySnapshot&)>&& func) const override;
+        bool forEachSnapshotInIndexRange(long first, long last, std::function<void(EntitySnapshot&)>&& func) const override;
+        bool forEachSnapshotInTimeRange(const Time& min, const Time& max, std::function<void(EntitySnapshot&)>&& func) const override;
+        bool forEachSnapshotBeforeOrAt(const Time& time, std::function<void(EntitySnapshot&)>&& func) const override;
+        bool forEachSnapshotBefore(const Time& time, std::function<void(EntitySnapshot&)>&& func) const override;
+
+        std::shared_ptr<EntitySnapshot> findSnapshot(const Time&) const override;
+        std::shared_ptr<EntitySnapshot> findLatestSnapshot() const override;
+        std::shared_ptr<EntitySnapshot> findLatestSnapshotBefore(const Time& time) const override;
+        std::shared_ptr<EntitySnapshot> findLatestSnapshotBeforeOrAt(const Time& time) const override;
+        std::shared_ptr<EntitySnapshot> findFirstSnapshotAfter(const Time& time) const override;
+        std::shared_ptr<EntitySnapshot> findFirstSnapshotAfterOrAt(const Time& time) const override;
+
+    protected:
+        std::string getExpectedFolderName() const override;
+    };
+
+} // namespace armarx::armem::server::ltm::disk
diff --git a/source/RobotAPI/libraries/armem/server/ltm/disk/EntitySnapshot.cpp b/source/RobotAPI/libraries/armem/server/ltm/disk/EntitySnapshot.cpp
new file mode 100644
index 000000000..204769226
--- /dev/null
+++ b/source/RobotAPI/libraries/armem/server/ltm/disk/EntitySnapshot.cpp
@@ -0,0 +1,131 @@
+// Header
+#include "EntitySnapshot.h"
+
+// STD / STL
+#include <iostream>
+#include <fstream>
+
+// ArmarX
+#include <ArmarXCore/core/time/TimeUtil.h>
+#include <ArmarXCore/core/logging/Logging.h>
+#include <RobotAPI/libraries/aron/core/data/variant/container/Dict.h>
+#include <RobotAPI/libraries/aron/converter/json/NLohmannJSONConverter.h>
+
+namespace armarx::armem::server::ltm::disk
+{
+
+    namespace
+    {
+        MemoryID getMemoryIDFromPath(const std::filesystem::path& p)
+        {
+            util::ensureFolderExists(p);
+
+            MemoryID m;
+            m.memoryName = p.parent_path().parent_path().parent_path().parent_path().filename();
+            m.coreSegmentName = p.parent_path().parent_path().parent_path().filename();
+            m.providerSegmentName = p.parent_path().parent_path().filename();
+            m.entityName = p.parent_path().filename();
+            m.timestamp = IceUtil::Time::microSeconds(std::stol(p.filename()));
+            return m;
+        }
+    }
+
+    EntitySnapshot::EntitySnapshot(const std::filesystem::path& p) :
+        EntitySnapshotBase(getMemoryIDFromPath(p)),
+        DiskStorage(p)
+    {
+    }
+
+    std::string EntitySnapshot::getExpectedFolderName() const
+    {
+        return name();
+    }
+
+    armem::wm::EntitySnapshot EntitySnapshot::loadAll() const
+    {
+        std::filesystem::path p = path;
+        util::ensureFolderExists(p, false);
+
+        armem::wm::EntitySnapshot e(id());
+
+        for (unsigned int i = 0; i < 1000; ++i) // 1000 is max size for instances in a single timestamp
+        {
+            if (!util::checkIfFolderExists(p / std::to_string(i)))
+            {
+                break;
+            }
+
+            // add instance. Do not set data, since we only return references
+            e.addInstance();
+        }
+        return e;
+    }
+
+    void EntitySnapshot::convert(armem::wm::EntitySnapshot& e) const
+    {
+        // Get data from disk
+        std::filesystem::path p = path;
+        util::ensureFolderExists(p, false);
+
+        for (unsigned int i = 0; i < e.size(); ++i)
+        {
+            util::ensureFolderExists(p / std::to_string(i), false);
+
+            std::filesystem::path data = p / std::to_string(i) / constantes::DATA_FILENAME;
+            std::filesystem::path metadata = p / std::to_string(i) / constantes::METADATA_FILENAME;
+
+            util::ensureFileExists(data);
+
+            auto& ins = e.getInstance(i);
+
+            std::ifstream dataifs(data);
+            std::string datafilecontent((std::istreambuf_iterator<char>(dataifs)), (std::istreambuf_iterator<char>()));
+            nlohmann::json datajson = nlohmann::json::parse(datafilecontent);
+            auto dataaron = aron::converter::AronNlohmannJSONConverter::ConvertFromNlohmannJSONObject(datajson);
+
+            std::ifstream metadataifs(metadata);
+            std::string metadatafilecontent((std::istreambuf_iterator<char>(metadataifs)), (std::istreambuf_iterator<char>()));
+            nlohmann::json metadatajson = nlohmann::json::parse(metadatafilecontent);
+            auto metadataaron = aron::converter::AronNlohmannJSONConverter::ConvertFromNlohmannJSONObject(metadatajson);
+
+            from_aron(metadataaron, dataaron, ins);
+        }
+    }
+
+    void EntitySnapshot::store(const armem::wm::EntitySnapshot& e) const
+    {
+        std::filesystem::path p = path;
+        util::ensureFolderExists(p);
+
+        for (unsigned int i = 0; i < e.size(); ++i)
+        {
+            util::ensureFolderExists(p / std::to_string(i));
+
+            std::filesystem::path data = p / std::to_string(i) / constantes::DATA_FILENAME;
+            std::filesystem::path metadata = p / std::to_string(i) / constantes::METADATA_FILENAME;
+
+            if (util::checkIfFileExists(data) or util::checkIfFileExists(metadata))
+            {
+                continue;
+            }
+
+            auto& ins = e.getInstance(i);
+
+            auto dataaron = std::make_shared<aron::data::Dict>();
+            auto metadataaron = std::make_shared<aron::data::Dict>();
+            to_aron(metadataaron, dataaron, ins);
+            nlohmann::json datajson = aron::converter::AronNlohmannJSONConverter::ConvertToNlohmannJSON(dataaron);
+            nlohmann::json metadatajson = aron::converter::AronNlohmannJSONConverter::ConvertToNlohmannJSON(metadataaron);
+
+            std::ofstream dataofs;
+            dataofs.open(data);
+            dataofs << datajson.dump(2);
+            dataofs.close();
+
+            std::ofstream metadataofs;
+            metadataofs.open(metadata);
+            metadataofs << metadatajson.dump(2);
+            metadataofs.close();
+        }
+    }
+}
diff --git a/source/RobotAPI/libraries/armem/server/ltm/disk/EntitySnapshot.h b/source/RobotAPI/libraries/armem/server/ltm/disk/EntitySnapshot.h
new file mode 100644
index 000000000..50d01d254
--- /dev/null
+++ b/source/RobotAPI/libraries/armem/server/ltm/disk/EntitySnapshot.h
@@ -0,0 +1,28 @@
+#pragma once
+
+#include <filesystem>
+
+// Base Class
+#include "../detail/EntitySnapshotBase.h"
+#include "detail/DiskStorage.h"
+
+namespace armarx::armem::server::ltm::disk
+{
+
+    class EntitySnapshot :
+            public EntitySnapshotBase,
+            public DiskStorage
+    {
+    public:
+        using EntitySnapshotBase::EntitySnapshotBase;
+        EntitySnapshot(const std::filesystem::path&);
+
+        armem::wm::EntitySnapshot loadAll() const override;
+        void convert(armem::wm::EntitySnapshot&) const override;
+        void store(const armem::wm::EntitySnapshot&) const override;
+
+    protected:
+        std::string getExpectedFolderName() const override;
+    };
+
+} // namespace armarx::armem::server::ltm::disk
diff --git a/source/RobotAPI/libraries/armem/server/ltm/disk/Memory.cpp b/source/RobotAPI/libraries/armem/server/ltm/disk/Memory.cpp
new file mode 100644
index 000000000..b75a3f557
--- /dev/null
+++ b/source/RobotAPI/libraries/armem/server/ltm/disk/Memory.cpp
@@ -0,0 +1,142 @@
+// Header
+#include "Memory.h"
+
+// ArmarX
+#include <ArmarXCore/core/time/TimeUtil.h>
+#include <ArmarXCore/core/logging/Logging.h>
+
+namespace armarx::armem::server::ltm::disk
+{
+    namespace
+    {
+        MemoryID getMemoryIDFromPath(const std::filesystem::path& p)
+        {
+            util::ensureFolderExists(p);
+
+            MemoryID m;
+            m.memoryName = p.filename();
+            return m;
+        }
+    }
+
+    Memory::Memory() :
+        BufferedMemoryBase(),
+        DiskStorage()
+    {
+        setMemoryID(MemoryID("Test", ""));
+
+        /*std::string armarx_home = std::string(getenv("HOME")) + "/.armarx";
+        if (getenv("ARMARX_DEFAULTS_DIR"))
+        {
+            armarx_home = getenv("ARMARX_DEFAULTS_DIR");
+        }
+        path = armarx_home + "/armem/disk/data/db";*/
+        path = "/tmp/MemoryExport/" + getExpectedFolderName();
+    }
+
+    Memory::Memory(const std::filesystem::path& p) :
+        BufferedMemoryBase(),
+        DiskStorage(p)
+    {
+        setMemoryID(getMemoryIDFromPath(p));
+    }
+
+    std::string Memory::getExpectedFolderName() const
+    {
+        return id().memoryName;
+    }
+
+    bool Memory::forEachCoreSegment(std::function<void(CoreSegment&)>&& func) const
+    {
+        if (!checkPath())
+        {
+            return false;
+        }
+
+        std::filesystem::path p = path;
+        util::ensureFolderExists(p, false);
+
+        for (const auto& subdir : std::filesystem::directory_iterator(p))
+        {
+            std::filesystem::path subdirPath = subdir.path();
+            CoreSegment c(subdirPath);
+            func(c);
+        }
+        return true;
+    }
+
+    std::shared_ptr<CoreSegment> Memory::findCoreSegment(const std::string& n) const
+    {
+        if (!checkPath())
+        {
+            return {};
+        }
+
+        std::filesystem::path p = path;
+        util::ensureFolderExists(p, false);
+
+        std::filesystem::path subpath = p / n;
+        util::ensureFolderExists(subpath, false);
+        auto c = std::make_shared<CoreSegment>(subpath);
+        return c;
+    }
+
+    armem::wm::Memory Memory::loadAll()
+    {
+        TIMING_START(LTM_Memory_Load);
+
+        armem::wm::Memory m(id());
+
+        forEachCoreSegment([&m](CoreSegment& x) {
+            auto s = x.loadAll();
+            m.addCoreSegment(s);
+        });
+
+        TIMING_END_STREAM(LTM_Memory_Load, ARMARX_DEBUG);
+        return m;
+    }
+
+    void Memory::convert(armem::wm::Memory& m)
+    {
+        TIMING_START(LTM_Memory_Convert);
+
+        if (!checkPath())
+        {
+            return;
+        }
+
+        std::lock_guard l(ltm_mutex);
+        m.forEachCoreSegment([this](armem::wm::CoreSegment& e)
+        {
+            util::ensureFolderExists(std::filesystem::path(path) / e.id().coreSegmentName, false);
+            CoreSegment c(std::filesystem::path(path) / e.id().coreSegmentName);
+            c.convert(e);
+        });
+
+        TIMING_END_STREAM(LTM_Memory_Convert, ARMARX_DEBUG);
+    }
+
+    void Memory::store(const armem::wm::Memory& m)
+    {
+        TIMING_START(LTM_Memory_Store);
+
+        if (!checkPath())
+        {
+            return;
+        }
+
+        std::lock_guard l(ltm_mutex);
+
+        m.forEachCoreSegment([this](const armem::wm::CoreSegment& e)
+        {
+            util::ensureFolderExists(std::filesystem::path(path) / e.id().coreSegmentName);
+            CoreSegment c(std::filesystem::path(path) / e.id().coreSegmentName);
+            c.store(e);
+        });
+
+        // Finaly clear cache and put reference to lut
+        buffer.clear();
+
+        TIMING_END_STREAM(LTM_Memory_Store, ARMARX_DEBUG);
+    }
+}
diff --git a/source/RobotAPI/libraries/armem/server/ltm/disk/Memory.h b/source/RobotAPI/libraries/armem/server/ltm/disk/Memory.h
new file mode 100644
index 000000000..a32719de2
--- /dev/null
+++ b/source/RobotAPI/libraries/armem/server/ltm/disk/Memory.h
@@ -0,0 +1,34 @@
+#pragma once
+
+#include <filesystem>
+
+// Base Class
+#include "../detail/BufferedMemoryBase.h"
+#include "detail/DiskStorage.h"
+
+#include "CoreSegment.h"
+
+namespace armarx::armem::server::ltm::disk
+{
+    /// @brief A memory storing data in mongodb (needs 'armarx memory start' to start the mongod instance)
+    class Memory :
+            public BufferedMemoryBase<CoreSegment>,
+            public DiskStorage
+    {
+    public:
+        using BufferedMemoryBase::BufferedMemoryBase;
+        Memory();
+        Memory(const std::filesystem::path&);
+
+        armem::wm::Memory loadAll() override;
+        void convert(armem::wm::Memory&) override;
+        void store(const armem::wm::Memory&) override;
+
+        bool forEachCoreSegment(std::function<void(CoreSegment&)>&& func) const override;
+
+        std::shared_ptr<CoreSegment> findCoreSegment(const std::string&) const override;
+
+    protected:
+        std::string getExpectedFolderName() const override;
+    };
+} // namespace armarx::armem::server::ltm::disk
diff --git a/source/RobotAPI/libraries/armem/server/ltm/disk/MemoryManager.cpp b/source/RobotAPI/libraries/armem/server/ltm/disk/MemoryManager.cpp
deleted file mode 100644
index f503dc066..000000000
--- a/source/RobotAPI/libraries/armem/server/ltm/disk/MemoryManager.cpp
+++ /dev/null
@@ -1,119 +0,0 @@
-// Header
-#include "MemoryManager.h"
-
-// ArmarX
-#include <ArmarXCore/core/time/TimeUtil.h>
-#include <ArmarXCore/core/logging/Logging.h>
-#include <RobotAPI/libraries/aron/core/data/variant/container/Dict.h>
-#include <RobotAPI/libraries/armem/core/wm/aron_conversions.h>
-#include <RobotAPI/libraries/aron/converter/json/NLohmannJSONConverter.h>
-
-#include "operations.h"
-
-namespace armarx::armem::server::ltm::disk
-{
-    Memory::Memory() :
-        MemoryBase()
-    {
-        std::string armarx_home = std::string(getenv("HOME")) + "/.armarx";
-        if (getenv("ARMARX_DEFAULTS_DIR"))
-        {
-            armarx_home = getenv("ARMARX_DEFAULTS_DIR");
-        }
-        memoryPathString = armarx_home + "/diskmemory/data/db";
-    }
-
-    Memory::Memory(const std::string& s) :
-        MemoryBase(s)
-    {
-        std::string armarx_home = std::string(getenv("HOME")) + "/.armarx";
-        if (getenv("ARMARX_DEFAULTS_DIR"))
-        {
-            armarx_home = getenv("ARMARX_DEFAULTS_DIR");
-        }
-        memoryPathString = armarx_home + "/diskmemory/data/db";
-    }
-
-    Memory::Memory(const std::filesystem::path& p) :
-        MemoryBase(p.filename()),
-        memoryPath(p)
-    {
-    }
-
-    bool Memory::checkPath() const
-    {
-        // Check connection:
-        if (!std::filesystem::exists(memoryPath))
-        {
-            std::filesystem::create_directories(memoryPath);
-            return true;
-        }
-        else if (!std::filesystem::is_directory(memoryPath) || memoryPath.filename() != cache.name())
-        {
-            ARMARX_WARNING << deactivateSpam("LTM_PathError_" + cache.name())
-                           << "The entered path is not valid. Please use a path leading to a memory folder with name: " << cache.name() << "."
-                           << "\n\n";
-            return false;
-        }
-
-        return true;
-    }
-
-    void Memory::reload()
-    {
-        memoryPath = std::filesystem::path(memoryPathString);
-
-        TIMING_START(LTM_Reload);
-
-        if (!checkPath())
-        {
-            return;
-        }
-
-        std::lock_guard l(ltm_mutex);
-        armem::wm::Memory temp(lut.id());
-        util::load(memoryPath, temp);
-
-        lut.append(temp);
-
-        TIMING_END_STREAM(LTM_Reload, ARMARX_DEBUG);
-    }
-
-    void Memory::convert(armem::wm::Memory& m)
-    {
-        memoryPath = std::filesystem::path(memoryPathString);
-
-        TIMING_START(LTM_Convert);
-        if (!checkPath())
-        {
-            return;
-        }
-
-        std::lock_guard l(ltm_mutex);
-        util::convert(memoryPath, m);
-
-        TIMING_END_STREAM(LTM_Convert, ARMARX_DEBUG);
-    }
-
-    void Memory::encodeAndStore()
-    {
-        memoryPath = std::filesystem::path(memoryPathString);
-
-        TIMING_START(LTM_Encode);
-        if (!checkPath())
-        {
-            return;
-        }
-
-        std::lock_guard l(ltm_mutex);
-        util::store(memoryPath, cache);
-
-        // what to do with clear text data after encoding?
-        // TODO!
-
-        // Finaly clear cache and put reference to lut
-        moveCacheToLUTAndClearCache();
-
-        TIMING_END_STREAM(LTM_Encode, ARMARX_DEBUG);
-    }
-}
diff --git a/source/RobotAPI/libraries/armem/server/ltm/disk/MemoryManager.h b/source/RobotAPI/libraries/armem/server/ltm/disk/MemoryManager.h
deleted file mode 100644
index 66a6a3e42..000000000
--- a/source/RobotAPI/libraries/armem/server/ltm/disk/MemoryManager.h
+++ /dev/null
@@ -1,39 +0,0 @@
-#pragma once
-
-#include <filesystem>
-#include <mutex>
-#include <optional>
-
-#include <RobotAPI/libraries/armem/server/ltm/LongtermMemoryBase.h>
-
-
-namespace armarx::armem::server::ltm::disk
-{
-    /// @brief A memory storing data in mongodb (needs 'armarx memory start' to start the mongod instance)
-    class Memory : public MemoryBase
-    {
-        using Base = MemoryBase;
-
-    public:
-        using Base::convert;
-
-        Memory();
-        Memory(const std::string&);
-        Memory(const std::filesystem::path&);
-
-        void reload() override;
-        void convert(armem::wm::Memory&) override;
-        void encodeAndStore() override;
-
-    private:
-        bool checkPath() const;
-
-    public:
-        std::string memoryPathString;
-
-    private:
-        std::filesystem::path memoryPath;
-
-    };
-
-} // namespace armarx::armem::server::ltm::disk
diff --git a/source/RobotAPI/libraries/armem/server/ltm/disk/ProviderSegment.cpp b/source/RobotAPI/libraries/armem/server/ltm/disk/ProviderSegment.cpp
new file mode 100644
index 000000000..bc3310c11
--- /dev/null
+++ b/source/RobotAPI/libraries/armem/server/ltm/disk/ProviderSegment.cpp
@@ -0,0 +1,101 @@
+// Header
+#include "ProviderSegment.h"
+
+// ArmarX
+#include <ArmarXCore/core/time/TimeUtil.h>
+#include <ArmarXCore/core/logging/Logging.h>
+
+namespace armarx::armem::server::ltm::disk
+{
+    namespace
+    {
+        MemoryID getMemoryIDFromPath(const std::filesystem::path& p)
+        {
+            util::ensureFolderExists(p);
+
+            MemoryID m;
+            m.memoryName = p.parent_path().parent_path().filename();
+            m.coreSegmentName = p.parent_path().filename();
+            m.providerSegmentName = p.filename();
+            return m;
+        }
+    }
+
+    ProviderSegment::ProviderSegment(const std::filesystem::path& p) :
+        ProviderSegmentBase(getMemoryIDFromPath(p)),
+        DiskStorage(p)
+    {
+    }
+
+    bool ProviderSegment::forEachEntity(std::function<void(Entity&)>&& func) const
+    {
+        if (!checkPath())
+        {
+            return false;
+        }
+
+        std::filesystem::path p = path;
+        util::ensureFolderExists(p, false);
+
+        for (const auto& subdir : std::filesystem::directory_iterator(p))
+        {
+            std::filesystem::path subdirPath = subdir.path();
+            Entity c(subdirPath);
+            func(c);
+        }
+        return true;
+    }
+
+    std::shared_ptr<Entity> ProviderSegment::findEntity(const std::string& n) const
+    {
+        if (!checkPath())
+        {
+            return {};
+        }
+
+        std::filesystem::path p = path;
+        util::ensureFolderExists(p, false);
+
+        std::filesystem::path subpath = p / n;
+        util::ensureFolderExists(subpath, false);
+        auto c = std::make_shared<Entity>(subpath);
+        return c;
+    }
+
+    std::string ProviderSegment::getExpectedFolderName() const
+    {
+        return name();
+    }
+
+    armem::wm::ProviderSegment ProviderSegment::loadAll()
+    {
+        armem::wm::ProviderSegment e(id());
+
+        forEachEntity([&e](Entity& x) {
+            auto s = x.loadAll();
+            e.addEntity(s);
+        });
+
+        return e;
+    }
+
+    void ProviderSegment::convert(armem::wm::ProviderSegment& p)
+    {
+        p.forEachEntity([this](armem::wm::Entity& e)
+        {
+            util::ensureFolderExists(std::filesystem::path(path) / e.id().entityName, false);
+            Entity c(std::filesystem::path(path) / e.id().entityName);
+            c.convert(e);
+        });
+    }
+
+    void ProviderSegment::store(const armem::wm::ProviderSegment& p)
+    {
+        p.forEachEntity([this](const armem::wm::Entity& e)
+        {
+            util::ensureFolderExists(std::filesystem::path(path) / e.id().entityName);
+            Entity c(std::filesystem::path(path) / e.id().entityName);
+            c.store(e);
+        });
+    }
+}
diff --git a/source/RobotAPI/libraries/armem/server/ltm/disk/ProviderSegment.h b/source/RobotAPI/libraries/armem/server/ltm/disk/ProviderSegment.h
new file mode 100644
index 000000000..265902756
--- /dev/null
+++ b/source/RobotAPI/libraries/armem/server/ltm/disk/ProviderSegment.h
@@ -0,0 +1,33 @@
+#pragma once
+
+#include <filesystem>
+
+// Base Class
+#include "../detail/ProviderSegmentBase.h"
+#include "detail/DiskStorage.h"
+
+#include "Entity.h"
+
+namespace armarx::armem::server::ltm::disk
+{
+    class ProviderSegment :
+            public ProviderSegmentBase<Entity>,
+            public DiskStorage
+    {
+    public:
+        using ProviderSegmentBase::ProviderSegmentBase;
+        ProviderSegment(const std::filesystem::path&);
+
+        armem::wm::ProviderSegment loadAll() override;
+        void convert(armem::wm::ProviderSegment&) override;
+        void store(const armem::wm::ProviderSegment&) override;
+
+        bool forEachEntity(std::function<void(Entity&)>&& func) const override;
+
+        std::shared_ptr<Entity> findEntity(const std::string&) const override;
+
+    protected:
+        std::string getExpectedFolderName() const override;
+    };
+
+} // namespace armarx::armem::server::ltm::disk
diff --git a/source/RobotAPI/libraries/armem/server/ltm/disk/detail/Data.cpp b/source/RobotAPI/libraries/armem/server/ltm/disk/detail/Data.cpp
new file mode 100644
index 000000000..d6eef0874
--- /dev/null
+++ b/source/RobotAPI/libraries/armem/server/ltm/disk/detail/Data.cpp
@@ -0,0 +1,7 @@
+// Header
+#include "Data.h"
+
+namespace armarx::armem::server::ltm::disk
+{
+
+}
diff --git a/source/RobotAPI/libraries/armem/server/ltm/disk/detail/Data.h b/source/RobotAPI/libraries/armem/server/ltm/disk/detail/Data.h
new file mode 100644
index 000000000..f5dc9078f
--- /dev/null
+++ b/source/RobotAPI/libraries/armem/server/ltm/disk/detail/Data.h
@@ -0,0 +1,65 @@
+#pragma once
+
+#include <filesystem>
+
+#include "../../../../core/error.h"
+
+namespace armarx::armem::server::ltm::disk
+{
+    namespace constantes
+    {
+        const std::string TYPE_FILENAME = "type.aron.json";
+        const std::string DATA_FILENAME = "data.aron.json";
+        const std::string METADATA_FILENAME = "metadata.aron.json";
+    }
+
+    namespace util
+    {
+        // check whether a string is a number (e.g. timestamp folders)
+        inline bool isNumber(const std::string& s)
+        {
+            for (char const& ch : s)
+            {
+                if (std::isdigit(ch) == 0)
+                {
+                    return false;
+                }
+            }
+            return true;
+        }
+
+        inline bool checkIfFolderExists(const std::filesystem::path& p)
+        {
+            return std::filesystem::exists(p) and std::filesystem::is_directory(p);
+        }
+
+        inline void ensureFolderExists(const std::filesystem::path& p, bool createIfNotExistent = true)
+        {
+            if (!std::filesystem::exists(p))
+            {
+                if (createIfNotExistent)
+                {
+                    std::filesystem::create_directory(p);
+                }
+            }
+            if (!std::filesystem::is_directory(p))
+            {
+                throw error::ArMemError("Could not find folder: " + p.string());
+            }
+        }
+
+        inline bool checkIfFileExists(const std::filesystem::path& p)
+        {
+            return std::filesystem::exists(p) and std::filesystem::is_regular_file(p);
+        }
+
+        inline void ensureFileExists(const std::filesystem::path& p)
+        {
+            if (!std::filesystem::exists(p) || !std::filesystem::is_regular_file(p))
+            {
+                // not found
+                throw error::ArMemError("Could not find file: " + p.string());
+            }
+        }
+    }
+} // namespace armarx::armem::server::ltm::disk
diff --git a/source/RobotAPI/libraries/armem/server/ltm/disk/detail/DiskStorage.cpp b/source/RobotAPI/libraries/armem/server/ltm/disk/detail/DiskStorage.cpp
new file mode 100644
index 000000000..21ebd7aef
--- /dev/null
+++ b/source/RobotAPI/libraries/armem/server/ltm/disk/detail/DiskStorage.cpp
@@ -0,0 +1,40 @@
+// Header
+#include "DiskStorage.h"
+
+// ArmarX
+#include <ArmarXCore/core/time/TimeUtil.h>
+#include <ArmarXCore/core/logging/Logging.h>
+
+namespace armarx::armem::server::ltm::disk
+{
+    DiskStorage::DiskStorage(const std::filesystem::path& p) :
+        path(p.string())
+    {
+    }
+
+    bool DiskStorage::checkPath() const
+    {
+        std::filesystem::path memoryP(path);
+
+        // Check connection:
+        if (!std::filesystem::exists(path))
+        {
+            std::filesystem::create_directories(path);
+            return true;
+        }
+        else if (std::string expectedFolderName = getExpectedFolderName(); !std::filesystem::is_directory(path) || memoryP.filename() != expectedFolderName)
+        {
+            ARMARX_WARNING << deactivateSpam("LTM_PathError_" + expectedFolderName)
+                           << "The entered path is not valid. Please use a path leading to a memory folder with name: " << expectedFolderName << "."
+                           << "\n\n";
+            return false;
+        }
+
+        return true;
+    }
+
+    void DiskStorage::setPath(const std::string& p)
+    {
+        path = p;
+    }
+}
diff --git a/source/RobotAPI/libraries/armem/server/ltm/disk/detail/DiskStorage.h b/source/RobotAPI/libraries/armem/server/ltm/disk/detail/DiskStorage.h
new file mode 100644
index 000000000..201322615
--- /dev/null
+++ b/source/RobotAPI/libraries/armem/server/ltm/disk/detail/DiskStorage.h
@@ -0,0 +1,25 @@
+#pragma once
+
+#include <filesystem>
+
+#include "Data.h"
+
+namespace armarx::armem::server::ltm::disk
+{
+    class DiskStorage
+    {
+    public:
+        DiskStorage() = default;
+        DiskStorage(const std::filesystem::path&);
+
+        void setPath(const std::string&);
+
+    protected:
+        bool checkPath() const;
+
+        virtual std::string getExpectedFolderName() const = 0;
+
+    public:
+        std::string path;
+    };
+} // namespace armarx::armem::server::ltm::disk
diff --git a/source/RobotAPI/libraries/armem/server/ltm/disk/operations.cpp b/source/RobotAPI/libraries/armem/server/ltm/disk/operations.cpp
deleted file mode 100644
index 34c675762..000000000
--- a/source/RobotAPI/libraries/armem/server/ltm/disk/operations.cpp
+++ /dev/null
@@ -1,281 +0,0 @@
-#include "operations.h"
-
-// STD / STL
-#include <iostream>
-#include <fstream>
-
-// Simox
-#include <SimoxUtility/json.h>
-
-#include "../operations.h"
-#include <RobotAPI/libraries/aron/converter/json/NLohmannJSONConverter.h>
-#include <RobotAPI/libraries/armem/core/wm/aron_conversions.h>
-
-namespace armarx::armem::server::ltm::disk::util
-{
-
-    namespace fs = std::filesystem;
-
-    namespace
-    {
-        // check whether a string is a number (timestamp folders)
-        bool isNumber(const std::string& s)
-        {
-            for (char const& ch : s)
-            {
-                if (std::isdigit(ch) == 0)
-                {
-                    return false;
-                }
-            }
-            return true;
-        }
-
-        void ensureFolderExists(const fs::path& p)
-        {
-            if (!fs::exists(p))
-            {
-                // not found
-                fs::create_directory(p);
-            }
-            if (!fs::is_directory(p))
-            {
-                throw error::ArMemError("Could not create the folder: " + p.string());
-            }
-        }
-    }
-
-    void load(const std::filesystem::path& directory, armem::wm::Memory& m)
-    {
-        for (const auto& d : std::filesystem::directory_iterator(directory))
-        {
-            if (!d.is_directory())
-            {
-                continue;
-            }
-
-            std::string k = d.path().filename();
-            if (m.hasCoreSegment(k))
-            {
-                throw error::ArMemError("Somehow the (memory) container already contains the key k = " + k + ". This should not happen.");
-            }
-            auto& cSeg = m.addCoreSegment(k);
-            load((directory / k), cSeg);
-        }
-    }
-
-    void load(const std::filesystem::path& directory, armem::wm::CoreSegment& c)
-    {
-        for (const auto& d : std::filesystem::directory_iterator(directory))
-        {
-            if (!d.is_directory())
-            {
-                continue;
-            }
-
-            std::string k = d.path().filename();
-            if (c.hasProviderSegment(k))
-            {
-                throw error::ArMemError("Somehow the (core) container already contains the key k = " + k + ". This should not happen.");
-            }
-            auto& pSeg = c.addProviderSegment(k);
-            load((directory / k), pSeg);
-        }
-    }
-
-    void load(const std::filesystem::path& directory, armem::wm::ProviderSegment& p)
-    {
-        for (const auto& d : std::filesystem::directory_iterator(directory))
-        {
-            if (!d.is_directory())
-            {
-                continue;
-            }
-
-            std::string k = d.path().filename();
-            if (p.hasEntity(k))
-            {
-                throw error::ArMemError("Somehow the (provider) container already contains the key k = " + k + ". This should not happen.");
-            }
-            auto& eSeg = p.addEntity(k);
-            load((directory / k), eSeg);
-        }
-    }
-
-    void load(const std::filesystem::path& directory, armem::wm::Entity& e)
-    {
-        for (const auto& d : std::filesystem::directory_iterator(directory))
-        {
-            if (!d.is_directory())
-            {
-                continue;
-            }
-
-            std::string k = d.path().filename();
-            if (!isNumber(k))
-            {
-                continue;
-            }
-
-            auto ts = armem::Time::microSeconds(std::stol(k));
-            // TODO catch exceptions?
-
-            if (e.hasSnapshot(ts))
-            {
-                throw error::ArMemError("Somehow the (entity) container already contains the key k = " + k + ". This should not happen.");
-            }
-
-            auto& sSeg = e.addSnapshot(ts);
-            for (unsigned int i = 0; i < 10000; ++i) // ugly workaround to get the folders in the correct order
-            {
-                fs::path p = d / std::to_string(i);
-                if (!fs::exists(p) || !fs::is_directory(p))
-                {
-                    // early stopping
-                    break;
-                }
-
-                fs::path data = p / constantes::DATA_FILENAME;
-                if (!fs::exists(data) || !fs::is_regular_file(data))
-                {
-                    // do not set data
-                    continue;
-                }
-
-                // else we have an instance
-                std::ifstream ifs(data);
-                std::string file_content((std::istreambuf_iterator<char>(ifs)), (std::istreambuf_iterator<char>()));
-
-                nlohmann::json j = nlohmann::json::parse(file_content);
-                auto aron = aron::converter::AronNlohmannJSONConverter::ConvertFromNlohmannJSONObject(j);
-
-                auto& instance = sSeg.addInstance();
-                from_aron(aron, instance);
-            }
-        }
-    }
-
-    void convert(const std::filesystem::path& directory, armem::wm::Memory& m)
-    {
-        m.forEachCoreSegment([&directory](armem::wm::CoreSegment & e)
-        {
-            convert((directory / e.id().coreSegmentName), e);
-        });
-    }
-
-    void convert(const std::filesystem::path& directory, armem::wm::CoreSegment& c)
-    {
-        c.forEachProviderSegment([&directory](armem::wm::ProviderSegment & e)
-        {
-            convert((directory / e.id().providerSegmentName), e);
-        });
-    }
-
-    void convert(const std::filesystem::path& directory, armem::wm::ProviderSegment& p)
-    {
-        p.forEachEntity([&directory](armem::wm::Entity & e)
-        {
-            convert((directory / e.id().entityName), e);
-        });
-    }
-
-    void convert(const std::filesystem::path& directory, armem::wm::Entity& e)
-    {
-        e.forEachSnapshot([&directory](armem::wm::EntitySnapshot & e)
-        {
-            if (!ltm::util::entityHasData(e)) // an entry from the lut (probably... for now we assume that every entry either has data (cache) or has null (lut))
-            {
-                // Get data from mongodb
-                auto p = directory / std::to_string(e.id().timestamp.toMicroSeconds());
-
-                if (fs::exists(p) && fs::is_directory(p))
-                {
-                    for (unsigned int i = 0; i < e.size(); ++i)
-                    {
-                        auto data = p / std::to_string(i) / constantes::DATA_FILENAME;
-
-                        if (fs::exists(data) && fs::is_regular_file(data))
-                        {
-                            auto& ins = e.getInstance(i);
-
-                            std::ifstream ifs(data);
-                            std::string file_content((std::istreambuf_iterator<char>(ifs)), (std::istreambuf_iterator<char>()));
-                            nlohmann::json doc = nlohmann::json::parse(file_content);
-
-                            auto aron = aron::converter::AronNlohmannJSONConverter::ConvertFromNlohmannJSONObject(doc);
-
-                            wm::EntityInstance tmp(e.id().withInstanceIndex(i));
-                            from_aron(aron, tmp);
-
-                            ins.data() = tmp.data();
-                        }
-                    }
-                }
-            }
-        });
-    }
-
-    void store(const std::filesystem::path& directory, const armem::wm::Memory& m)
-    {
-        m.forEachCoreSegment([&directory](armem::wm::CoreSegment & e)
-        {
-            fs::path cPath = directory / e.id().coreSegmentName;
-            ensureFolderExists(cPath);
-            store(cPath, e);
-        });
-    }
-
-    void store(const std::filesystem::path& directory, const armem::wm::CoreSegment& c)
-    {
-        c.forEachProviderSegment([&directory](armem::wm::ProviderSegment & e)
-        {
-            fs::path pPath = directory / e.id().providerSegmentName;
-            ensureFolderExists(pPath);
-            store(pPath, e);
-        });
-    }
-
-    void store(const std::filesystem::path& directory, const armem::wm::ProviderSegment& p)
-    {
-        p.forEachEntity([&directory](armem::wm::Entity & e)
-        {
-            fs::path ePath = directory / e.id().entityName;
-            ensureFolderExists(ePath);
-            store(ePath, e);
-        });
-    }
-    void store(const std::filesystem::path& directory, const armem::wm::Entity& e)
-    {
-        e.forEachSnapshot([&directory](armem::wm::EntitySnapshot & e)
-        {
-            fs::path sPath = directory / std::to_string(e.id().timestamp.toMicroSeconds());
-            ensureFolderExists(sPath);
-
-            e.forEachInstance([&sPath](armem::wm::EntityInstance & e)
-            {
-                fs::path iPath = sPath / std::to_string(e.id().instanceIndex);
-                if (fs::exists(iPath))
-                {
-                    // if instance already exists, we skip
-                    return;
-                }
-
-                ensureFolderExists(iPath);
-
-                fs::path data = iPath / constantes::DATA_FILENAME;
-                fs::remove(data); // Should not be the case. Anyway, if it happens, create new file!
-
-                std::ofstream ofs;
-                ofs.open(data);
-
-                auto aron = std::make_shared<aron::data::Dict>();
-                to_aron(aron, e);
-                nlohmann::json j = aron::converter::AronNlohmannJSONConverter::ConvertToNlohmannJSON(aron);
-
-                ofs << j.dump(2);
-                ofs.close();
-            });
-        });
-    }
-
-} // namespace armarx::armem::server::ltm
diff --git a/source/RobotAPI/libraries/armem/server/ltm/disk/operations.h b/source/RobotAPI/libraries/armem/server/ltm/disk/operations.h
deleted file mode 100644
index 5e930ff7b..000000000
--- a/source/RobotAPI/libraries/armem/server/ltm/disk/operations.h
+++ /dev/null
@@ -1,36 +0,0 @@
-#pragma once
-
-#include <filesystem>
-
-#include <RobotAPI/libraries/armem/core/forward_declarations.h>
-#include <RobotAPI/libraries/armem/server/forward_declarations.h>
-
-
-namespace armarx::armem::server::ltm::disk
-{
-
-    namespace constantes
-    {
-        const std::string TYPE_FILENAME = "type.aron.ltm.json";
-        const std::string DATA_FILENAME = "data.aron.ltm.json";
-    }
-
-    namespace util
-    {
-        void load(const std::filesystem::path& directory, armem::wm::Memory& memory);
-        void load(const std::filesystem::path& directory, armem::wm::CoreSegment& memory);
-        void load(const std::filesystem::path& directory, armem::wm::ProviderSegment& memory);
-        void load(const std::filesystem::path& directory, armem::wm::Entity& memory);
-
-        void convert(const std::filesystem::path& directory, armem::wm::Memory& memory);
-        void convert(const std::filesystem::path& directory, armem::wm::CoreSegment& memory);
-        void convert(const std::filesystem::path& directory, armem::wm::ProviderSegment& memory);
-        void convert(const std::filesystem::path& directory, armem::wm::Entity& memory);
-
-        void store(const std::filesystem::path& directory, const armem::wm::Memory& memory);
-        void store(const std::filesystem::path& directory, const armem::wm::CoreSegment& memory);
-        void store(const std::filesystem::path& directory, const armem::wm::ProviderSegment& memory);
-        void store(const std::filesystem::path& directory, const armem::wm::Entity& memory);
-    }
-
-} // namespace armarx::armem::server::ltm::disk
diff --git a/source/RobotAPI/libraries/armem/server/ltm/mongodb/ConnectionManager.cpp b/source/RobotAPI/libraries/armem/server/ltm/legacy/mongodb/ConnectionManager.cpp
similarity index 100%
rename from source/RobotAPI/libraries/armem/server/ltm/mongodb/ConnectionManager.cpp
rename to source/RobotAPI/libraries/armem/server/ltm/legacy/mongodb/ConnectionManager.cpp
diff --git a/source/RobotAPI/libraries/armem/server/ltm/mongodb/ConnectionManager.h b/source/RobotAPI/libraries/armem/server/ltm/legacy/mongodb/ConnectionManager.h
similarity index 100%
rename from source/RobotAPI/libraries/armem/server/ltm/mongodb/ConnectionManager.h
rename to source/RobotAPI/libraries/armem/server/ltm/legacy/mongodb/ConnectionManager.h
diff --git a/source/RobotAPI/libraries/armem/server/ltm/mongodb/MemoryManager.cpp b/source/RobotAPI/libraries/armem/server/ltm/legacy/mongodb/MemoryManager.cpp
similarity index 100%
rename from source/RobotAPI/libraries/armem/server/ltm/mongodb/MemoryManager.cpp
rename to source/RobotAPI/libraries/armem/server/ltm/legacy/mongodb/MemoryManager.cpp
diff --git a/source/RobotAPI/libraries/armem/server/ltm/mongodb/MemoryManager.h b/source/RobotAPI/libraries/armem/server/ltm/legacy/mongodb/MemoryManager.h
similarity index 95%
rename from source/RobotAPI/libraries/armem/server/ltm/mongodb/MemoryManager.h
rename to source/RobotAPI/libraries/armem/server/ltm/legacy/mongodb/MemoryManager.h
index 99a728f8d..6809bb596 100644
--- a/source/RobotAPI/libraries/armem/server/ltm/mongodb/MemoryManager.h
+++ b/source/RobotAPI/libraries/armem/server/ltm/legacy/mongodb/MemoryManager.h
@@ -5,7 +5,7 @@
 #include <optional>
 
 // Base Class
-#include "../LongtermMemoryBase.h"
+#include "../MemoryBase.h"
 
 // Data
 # include "ConnectionManager.h"
diff --git a/source/RobotAPI/libraries/armem/server/ltm/mongodb/operations.cpp b/source/RobotAPI/libraries/armem/server/ltm/legacy/mongodb/operations.cpp
similarity index 100%
rename from source/RobotAPI/libraries/armem/server/ltm/mongodb/operations.cpp
rename to source/RobotAPI/libraries/armem/server/ltm/legacy/mongodb/operations.cpp
diff --git a/source/RobotAPI/libraries/armem/server/ltm/mongodb/operations.h b/source/RobotAPI/libraries/armem/server/ltm/legacy/mongodb/operations.h
similarity index 100%
rename from source/RobotAPI/libraries/armem/server/ltm/mongodb/operations.h
rename to source/RobotAPI/libraries/armem/server/ltm/legacy/mongodb/operations.h
diff --git a/source/RobotAPI/libraries/armem/server/ltm/operations.cpp b/source/RobotAPI/libraries/armem/server/ltm/operations.cpp
deleted file mode 100644
index 188f0f547..000000000
--- a/source/RobotAPI/libraries/armem/server/ltm/operations.cpp
+++ /dev/null
@@ -1,22 +0,0 @@
-#include "operations.h"
-
-#include <RobotAPI/libraries/armem/server/wm/memory_definitions.h>
-
-namespace armarx::armem::server::ltm::util
-{
-    bool entityHasData(const armem::wm::EntitySnapshot& e)
-    {
-        // check whether all data is nullptr
-        bool allDataIsNull = e.size() > 0;
-        e.forEachInstance([&allDataIsNull](armem::wm::EntityInstance & e)
-        {
-            if (e.data())
-            {
-                allDataIsNull = false;
-                return false; // means break
-            }
-            return true;
-        });
-        return !allDataIsNull;
-    }
-} // namespace armarx::armem::server::ltm
diff --git a/source/RobotAPI/libraries/armem/server/ltm/operations.h b/source/RobotAPI/libraries/armem/server/ltm/operations.h
deleted file mode 100644
index b430afdf1..000000000
--- a/source/RobotAPI/libraries/armem/server/ltm/operations.h
+++ /dev/null
@@ -1,13 +0,0 @@
-#pragma once
-
-#include <RobotAPI/libraries/armem/core/forward_declarations.h>
-#include <RobotAPI/libraries/armem/server/forward_declarations.h>
-
-namespace armarx::armem::server::ltm
-{
-    namespace util
-    {
-        bool entityHasData(const armem::wm::EntitySnapshot& e);
-    }
-
-} // namespace armarx::armem::server::ltm
diff --git a/source/RobotAPI/libraries/armem/server/plugins/Plugin.cpp b/source/RobotAPI/libraries/armem/server/plugins/Plugin.cpp
index 93c701eaf..62ea8e632 100644
--- a/source/RobotAPI/libraries/armem/server/plugins/Plugin.cpp
+++ b/source/RobotAPI/libraries/armem/server/plugins/Plugin.cpp
@@ -43,7 +43,7 @@ namespace armarx::armem::server::plugins
             properties->optional(longtermMemory.dbsettings.database, prefix + "ltm.dbdatabase", "The name of the database you want to use for this memory. You can have multiple memories in one database.");*/
 
             // stuff if disk memory
-            properties->optional(longtermMemory.memoryPathString, "ltm.storagepath", "The path to the memory storage.");
+            properties->optional(longtermMemory.path, "ltm.storagepath", "The path to the memory storage.");
         }
 
         // Publish memory updates topic
@@ -60,12 +60,6 @@ namespace armarx::armem::server::plugins
             registerServer(parent);
         }
         iceAdapter.setMemoryListener(memoryTopic);
-
-        // establishing connection to ltm and mongodb
-        if (longtermMemoryEnabled)
-        {
-            longtermMemory.reload();
-        }
     }
 
 
@@ -81,7 +75,7 @@ namespace armarx::armem::server::plugins
     void Plugin::setMemoryName(const std::string& memoryName)
     {
         workingMemory.name() = memoryName;
-        longtermMemory.setName(memoryName);
+        longtermMemory.setMemoryID(workingMemory.id());
     }
 
 
diff --git a/source/RobotAPI/libraries/armem/server/plugins/Plugin.h b/source/RobotAPI/libraries/armem/server/plugins/Plugin.h
index 9d443c681..d5c7c0534 100644
--- a/source/RobotAPI/libraries/armem/server/plugins/Plugin.h
+++ b/source/RobotAPI/libraries/armem/server/plugins/Plugin.h
@@ -3,7 +3,6 @@
 #include <RobotAPI/libraries/armem/server/MemoryToIceAdapter.h>
 
 #include <RobotAPI/libraries/armem/server/wm/memory_definitions.h>
-#include <RobotAPI/libraries/armem/server/ltm/mongodb/MemoryManager.h>
 
 #include <RobotAPI/interface/armem/client/MemoryListenerInterface.h>
 #include <RobotAPI/interface/armem/mns/MemoryNameSystemInterface.h>
diff --git a/source/RobotAPI/libraries/armem/server/query_proc/base/BaseQueryProcessorBase.h b/source/RobotAPI/libraries/armem/server/query_proc/base/BaseQueryProcessorBase.h
index 73c662e04..b4ad4300d 100644
--- a/source/RobotAPI/libraries/armem/server/query_proc/base/BaseQueryProcessorBase.h
+++ b/source/RobotAPI/libraries/armem/server/query_proc/base/BaseQueryProcessorBase.h
@@ -36,7 +36,6 @@ namespace armarx::armem::server::query_proc::base
 
         virtual ~BaseQueryProcessorBase() = default;
 
-
         ResultT process(const QueryT& query, const DataT& data) const
         {
             ResultT result { data.id() };
diff --git a/source/RobotAPI/libraries/armem/server/query_proc/base/CoreSegmentQueryProcessorBase.h b/source/RobotAPI/libraries/armem/server/query_proc/base/CoreSegmentQueryProcessorBase.h
index 0c6199eac..dc84c257a 100644
--- a/source/RobotAPI/libraries/armem/server/query_proc/base/CoreSegmentQueryProcessorBase.h
+++ b/source/RobotAPI/libraries/armem/server/query_proc/base/CoreSegmentQueryProcessorBase.h
@@ -18,6 +18,8 @@ namespace armarx::armem::server::query_proc::base
     class CoreSegmentQueryProcessorBase :
         public BaseQueryProcessorBase<queryTarget, _CoreSegmentT, _ResultCoreSegmentT, armem::query::data::CoreSegmentQuery>
     {
+    protected:
+
         using Base = BaseQueryProcessorBase<queryTarget, _CoreSegmentT, _ResultCoreSegmentT, armem::query::data::CoreSegmentQuery>;
 
     public:
@@ -65,7 +67,7 @@ namespace armarx::armem::server::query_proc::base
             }
         }
 
-        void process(ResultCoreSegmentT& result,
+        virtual void process(ResultCoreSegmentT& result,
                      const armem::query::data::core::All& query,
                      const CoreSegmentT& coreSegment) const
         {
@@ -75,18 +77,17 @@ namespace armarx::armem::server::query_proc::base
             });
         }
 
-        void process(ResultCoreSegmentT& result,
+        virtual void process(ResultCoreSegmentT& result,
                      const armem::query::data::core::Single& query,
                      const CoreSegmentT& coreSegment) const
         {
-            const ProviderSegmentT* providerSegment = coreSegment.findProviderSegment(query.providerSegmentName);
-            if (providerSegment)
+            if (auto providerSegment = coreSegment.findProviderSegment(query.providerSegmentName))
             {
                 this->_processResult(result, *providerSegment, query);
             }
         }
 
-        void process(ResultCoreSegmentT& result,
+        virtual void process(ResultCoreSegmentT& result,
                      const armem::query::data::core::Regex& query,
                      const CoreSegmentT& coreSegment) const
         {
@@ -102,7 +103,7 @@ namespace armarx::armem::server::query_proc::base
         }
 
 
-    private:
+    protected:
 
         void _processResult(ResultCoreSegmentT& result,
                             const ProviderSegmentT& providerSegment,
diff --git a/source/RobotAPI/libraries/armem/server/query_proc/base/EntityQueryProcessorBase.h b/source/RobotAPI/libraries/armem/server/query_proc/base/EntityQueryProcessorBase.h
index b0210c37e..6179467a7 100644
--- a/source/RobotAPI/libraries/armem/server/query_proc/base/EntityQueryProcessorBase.h
+++ b/source/RobotAPI/libraries/armem/server/query_proc/base/EntityQueryProcessorBase.h
@@ -23,6 +23,8 @@ namespace armarx::armem::server::query_proc::base
     class EntityQueryProcessorBase :
         public BaseQueryProcessorBase<queryTarget, _EntityT, _ResultEntityT, armem::query::data::EntityQuery>
     {
+    protected:
+
         using Base = BaseQueryProcessorBase<queryTarget, _EntityT, _ResultEntityT, armem::query::data::EntityQuery>;
 
     public:
@@ -34,6 +36,8 @@ namespace armarx::armem::server::query_proc::base
         using ResultSnapshotT = typename ResultEntityT::EntitySnapshotT;
 
 
+    public:
+
         using Base::process;
         virtual void process(ResultEntityT& result,
                              const armem::query::data::EntityQuery& query,
@@ -74,37 +78,37 @@ namespace armarx::armem::server::query_proc::base
         }
 
 
-        void process(ResultEntityT& result,
+        virtual void process(ResultEntityT& result,
                      const armem::query::data::entity::All& query,
                      const EntityT& entity) const
         {
             (void) query;
             // Copy this entitiy and its contents.
 
-            entity.forEachSnapshot([this, &result](const EntitySnapshotT & snapshot)
+            entity.forEachSnapshot([this, &result](const EntitySnapshotT& snapshot)
             {
-                addResultSnapshot(result, snapshot);
+                this->addResultSnapshot(result, snapshot);
             });
         }
 
 
-        void process(ResultEntityT& result,
+        virtual void process(ResultEntityT& result,
                      const armem::query::data::entity::Single& query,
                      const EntityT& entity) const
         {
             if (query.timestamp < 0)
             {
-                if (const ResultSnapshotT* snapshot = entity.findLatestSnapshot())
+                if (auto snapshot = entity.findLatestSnapshot())
                 {
-                    addResultSnapshot(result, *snapshot);
+                    this->addResultSnapshot(result, *snapshot);
                 }
             }
             else
             {
                 const Time time = fromIce<Time>(query.timestamp);
-                if (const ResultSnapshotT* snapshot = entity.findSnapshot(time))
+                if (auto snapshot = entity.findSnapshot(time))
                 {
-                    addResultSnapshot(result, *snapshot);
+                    this->addResultSnapshot(result, *snapshot);
                 }
                 else
                 {
@@ -126,7 +130,7 @@ namespace armarx::armem::server::query_proc::base
         }
 
 
-        void process(ResultEntityT& result,
+        virtual void process(ResultEntityT& result,
                      const armem::query::data::entity::TimeRange& query,
                      const EntityT& entity) const
         {
@@ -139,7 +143,7 @@ namespace armarx::armem::server::query_proc::base
         }
 
 
-        void process(ResultEntityT& result,
+        virtual void process(ResultEntityT& result,
                      const armem::query::data::entity::IndexRange& query,
                      const EntityT& entity) const
         {
@@ -147,12 +151,12 @@ namespace armarx::armem::server::query_proc::base
                 query.first, query.last,
                 [this, &result](const EntitySnapshotT & snapshot)
             {
-                addResultSnapshot(result, snapshot);
+                this->addResultSnapshot(result, snapshot);
             });
         }
 
 
-        void process(ResultEntityT& result,
+        virtual void process(ResultEntityT& result,
                      const Time& min,
                      const Time& max,
                      const EntityT& entity,
@@ -163,31 +167,31 @@ namespace armarx::armem::server::query_proc::base
                 min, max,
                 [this, &result](const EntitySnapshotT & snapshot)
             {
-                addResultSnapshot(result, snapshot);
+                this->addResultSnapshot(result, snapshot);
             });
         }
 
 
-        void process(ResultEntityT& result,
+        virtual void process(ResultEntityT& result,
                      const armem::query::data::entity::BeforeOrAtTime& query,
                      const EntityT& entity) const
         {
             const Time referenceTimestamp = fromIce<Time>(query.timestamp);
-            detail::checkReferenceTimestampNonNegative(referenceTimestamp);
+            base::detail::checkReferenceTimestampNonNegative(referenceTimestamp);
 
-            if (auto* beforeOrAt = entity.findLatestSnapshotBeforeOrAt(referenceTimestamp))
+            if (auto beforeOrAt = entity.findLatestSnapshotBeforeOrAt(referenceTimestamp))
             {
-                addResultSnapshot(result, *beforeOrAt);
+                this->addResultSnapshot(result, *beforeOrAt);
             }
         }
 
 
-        void process(ResultEntityT& result,
+        virtual void process(ResultEntityT& result,
                      const armem::query::data::entity::BeforeTime& query,
                      const EntityT& entity) const
         {
             const Time referenceTimestamp = fromIce<Time>(query.timestamp);
-            detail::checkReferenceTimestampNonNegative(referenceTimestamp);
+            base::detail::checkReferenceTimestampNonNegative(referenceTimestamp);
 
             std::vector<const EntitySnapshotT*> befores;
             entity.forEachSnapshotBefore(referenceTimestamp, [&befores](const EntitySnapshotT & s)
@@ -208,17 +212,17 @@ namespace armarx::armem::server::query_proc::base
             for (size_t r = 0; r < num; ++r)
             {
                 size_t i = befores.size() - 1 - r;
-                addResultSnapshot(result, *befores[i]);
+                this->addResultSnapshot(result, *befores[i]);
             }
         }
 
 
-        void process(ResultEntityT& result,
+        virtual void process(ResultEntityT& result,
                      const armem::query::data::entity::TimeApprox& query,
                      const EntityT& entity) const
         {
             const Time referenceTimestamp = fromIce<Time>(query.timestamp);
-            detail::checkReferenceTimestampNonNegative(referenceTimestamp);
+            base::detail::checkReferenceTimestampNonNegative(referenceTimestamp);
 
             const float referenceTimestampMicroSeconds = referenceTimestamp.toMicroSeconds();
             const float epsDuration = fromIce<Time>(query.eps).toMicroSeconds();
@@ -235,13 +239,13 @@ namespace armarx::armem::server::query_proc::base
             };
 
             // last element before or at timestamp
-            if (auto* beforeOrAt = entity.findLatestSnapshotBeforeOrAt(referenceTimestamp))
+            if (auto beforeOrAt = entity.findLatestSnapshotBeforeOrAt(referenceTimestamp))
             {
                 const auto timestampOfMatchBefore = beforeOrAt->id().timestamp;
                 const auto isPerfectMatch = timestampOfMatchBefore == referenceTimestamp;
                 if (isInRange(timestampOfMatchBefore))
                 {
-                    addResultSnapshot(result, *beforeOrAt);
+                    this->addResultSnapshot(result, *beforeOrAt);
                 }
 
                 // earsly stop, not necessary to also get the next since the match is perfect
@@ -251,13 +255,13 @@ namespace armarx::armem::server::query_proc::base
                 }
 
                 // first element after or at timestamp (or at because of fewer checks, we can assure that there is not element at)
-                const auto* after = entity.findFirstSnapshotAfterOrAt(referenceTimestamp);
+                const auto after = entity.findFirstSnapshotAfterOrAt(referenceTimestamp);
                 if (after)
                 {
                     const auto timestampOfMatchAfter = after->id().timestamp;
                     if (isInRange(timestampOfMatchAfter))
                     {
-                        addResultSnapshot(result, *after);
+                        this->addResultSnapshot(result, *after);
                     }
                 }
             }
@@ -266,10 +270,7 @@ namespace armarx::armem::server::query_proc::base
 
     protected:
 
-        void addResultSnapshot(ResultEntityT& result, const EntitySnapshotT& snapshot) const
-        {
-            result.addSnapshot(snapshot);
-        }
+        virtual void addResultSnapshot(ResultEntityT& result, const EntitySnapshotT& snapshot) const = 0;
 
     };
 }
diff --git a/source/RobotAPI/libraries/armem/server/query_proc/base/MemoryQueryProcessorBase.h b/source/RobotAPI/libraries/armem/server/query_proc/base/MemoryQueryProcessorBase.h
index 91c41d9f5..85d632639 100644
--- a/source/RobotAPI/libraries/armem/server/query_proc/base/MemoryQueryProcessorBase.h
+++ b/source/RobotAPI/libraries/armem/server/query_proc/base/MemoryQueryProcessorBase.h
@@ -15,6 +15,8 @@ namespace armarx::armem::server::query_proc::base
     class MemoryQueryProcessorBase :
         public BaseQueryProcessorBase<queryTarget, _MemoryT, _ResultMemoryT, armem::query::data::MemoryQuery>
     {
+    protected:
+
         using Base = BaseQueryProcessorBase<queryTarget, _MemoryT, _ResultMemoryT, armem::query::data::MemoryQuery>;
 
     public:
@@ -67,32 +69,32 @@ namespace armarx::armem::server::query_proc::base
             }
         }
 
-        void process(ResultMemoryT& result,
+        virtual void process(ResultMemoryT& result,
                      const armem::query::data::memory::All& query,
                      const MemoryT& memory) const
         {
-            memory.forEachCoreSegment([this, &result, &query](const CoreSegmentT & coreSegment)
+            memory.forEachCoreSegment([this, &result, &query](const CoreSegmentT& coreSegment)
             {
                 this->_processResult(result, coreSegment, query);
             });
         }
 
-        void process(ResultMemoryT& result,
+        virtual void process(ResultMemoryT& result,
                      const armem::query::data::memory::Single& query,
                      const MemoryT& memory) const
         {
-            if (const CoreSegmentT* coreSegment = memory.findCoreSegment(query.coreSegmentName))
+            if (auto coreSegment = memory.findCoreSegment(query.coreSegmentName))
             {
                 this->_processResult(result, *coreSegment, query);
             }
         }
 
-        void process(ResultMemoryT& result,
+        virtual void process(ResultMemoryT& result,
                      const armem::query::data::memory::Regex& query,
                      const MemoryT& memory) const
         {
             const std::regex regex(query.coreSegmentNameRegex);
-            memory.forEachCoreSegment([this, &result, &query, &regex](const CoreSegmentT & coreSegment)
+            memory.forEachCoreSegment([this, &result, &query, &regex](const CoreSegmentT& coreSegment)
             {
                 if (std::regex_search(coreSegment.name(), regex))
                 {
@@ -102,7 +104,7 @@ namespace armarx::armem::server::query_proc::base
         }
 
 
-    private:
+    protected:
 
         void _processResult(ResultMemoryT& result,
                             const CoreSegmentT& coreSegment,
diff --git a/source/RobotAPI/libraries/armem/server/query_proc/base/ProviderSegmentQueryProcessorBase.h b/source/RobotAPI/libraries/armem/server/query_proc/base/ProviderSegmentQueryProcessorBase.h
index 46f146694..bc7f92031 100644
--- a/source/RobotAPI/libraries/armem/server/query_proc/base/ProviderSegmentQueryProcessorBase.h
+++ b/source/RobotAPI/libraries/armem/server/query_proc/base/ProviderSegmentQueryProcessorBase.h
@@ -16,6 +16,8 @@ namespace armarx::armem::server::query_proc::base
     class ProviderSegmentQueryProcessorBase :
         public BaseQueryProcessorBase<queryTarget, _ProviderSegmentT, _ResultProviderSegmentT, armem::query::data::ProviderSegmentQuery>
     {
+    protected:
+
         using Base = BaseQueryProcessorBase<queryTarget, _ProviderSegmentT, _ResultProviderSegmentT, armem::query::data::ProviderSegmentQuery>;
 
 
@@ -40,7 +42,6 @@ namespace armarx::armem::server::query_proc::base
         {
         }
 
-
         using Base::process;
         virtual void process(ResultProviderSegmentT& result,
                              const armem::query::data::ProviderSegmentQuery& query,
@@ -64,32 +65,32 @@ namespace armarx::armem::server::query_proc::base
             }
         }
 
-        void process(ResultProviderSegmentT& result,
+        virtual void process(ResultProviderSegmentT& result,
                      const armem::query::data::provider::All& query,
                      const ProviderSegmentT& providerSegment) const
         {
-            providerSegment.forEachEntity([this, &result, &query](const EntityT & entity)
+            providerSegment.forEachEntity([this, &result, &query](const EntityT& entity)
             {
                 this->_processResult(result, entity, query);
             });
         }
 
-        void process(ResultProviderSegmentT& result,
+        virtual void process(ResultProviderSegmentT& result,
                      const armem::query::data::provider::Single& query,
                      const ProviderSegmentT& providerSegment) const
         {
-            if (const EntityT* entity = providerSegment.findEntity(query.entityName))
+            if (auto entity = providerSegment.findEntity(query.entityName))
             {
                 this->_processResult(result, *entity, query);
             }
         }
 
-        void process(ResultProviderSegmentT& result,
+        virtual void process(ResultProviderSegmentT& result,
                      const armem::query::data::provider::Regex& query,
                      const ProviderSegmentT& providerSegment) const
         {
             const std::regex regex(query.entityNameRegex);
-            providerSegment.forEachEntity([this, &result, &query, &regex](const EntityT & entity)
+            providerSegment.forEachEntity([this, &result, &query, &regex](const EntityT& entity)
             {
                 if (std::regex_search(entity.name(), regex))
                 {
@@ -100,7 +101,7 @@ namespace armarx::armem::server::query_proc::base
         }
 
 
-    private:
+    protected:
 
         void _processResult(ResultProviderSegmentT& result,
                             const EntityT& entity,
diff --git a/source/RobotAPI/libraries/armem/server/query_proc/ltm.h b/source/RobotAPI/libraries/armem/server/query_proc/ltm.h
deleted file mode 100644
index 05734c2e1..000000000
--- a/source/RobotAPI/libraries/armem/server/query_proc/ltm.h
+++ /dev/null
@@ -1,32 +0,0 @@
-#pragma once
-
-#include <RobotAPI/libraries/armem/server/ltm/LongtermMemoryBase.h>
-#include <RobotAPI/libraries/armem/server/query_proc/base.h>
-
-
-namespace armarx::armem::server::query_proc::ltm
-{
-    static const base::QueryTarget queryTarget = query::data::QueryTarget::LTM;
-
-
-    class EntityQueryProcessor :
-        public base::EntityQueryProcessorBase<queryTarget, armem::wm::Entity, armem::wm::Entity>
-    {
-    };
-
-    class ProviderSegmentQueryProcessor :
-        public base::ProviderSegmentQueryProcessorBase <queryTarget, armem::wm::ProviderSegment, armem::wm::ProviderSegment, EntityQueryProcessor >
-    {
-    };
-
-    class CoreSegmentQueryProcessor :
-        public base::CoreSegmentQueryProcessorBase <queryTarget, armem::wm::CoreSegment, armem::wm::CoreSegment, ProviderSegmentQueryProcessor>
-    {
-    };
-
-    class MemoryQueryProcessor :
-        public base::MemoryQueryProcessorBase <queryTarget, armem::wm::Memory, armem::wm::Memory, CoreSegmentQueryProcessor >
-    {
-    };
-
-}
diff --git a/source/RobotAPI/libraries/armem/server/query_proc/ltm/detail/CoreSegmentQueryProcessorBase.cpp b/source/RobotAPI/libraries/armem/server/query_proc/ltm/detail/CoreSegmentQueryProcessorBase.cpp
new file mode 100644
index 000000000..63e7ff349
--- /dev/null
+++ b/source/RobotAPI/libraries/armem/server/query_proc/ltm/detail/CoreSegmentQueryProcessorBase.cpp
@@ -0,0 +1 @@
+#include "CoreSegmentQueryProcessorBase.h"
diff --git a/source/RobotAPI/libraries/armem/server/query_proc/ltm/detail/CoreSegmentQueryProcessorBase.h b/source/RobotAPI/libraries/armem/server/query_proc/ltm/detail/CoreSegmentQueryProcessorBase.h
new file mode 100644
index 000000000..0f06af9da
--- /dev/null
+++ b/source/RobotAPI/libraries/armem/server/query_proc/ltm/detail/CoreSegmentQueryProcessorBase.h
@@ -0,0 +1,36 @@
+#pragma once
+
+#include "../../base/CoreSegmentQueryProcessorBase.h"
+
+
+namespace armarx::armem::server::query_proc::ltm::detail
+{
+
+    /**
+     * @brief Handles memory queries.
+     */
+    template <base::QueryTarget queryTarget, class _CoreSegmentT, class _ResultCoreSegmentT, class _ChildProcessorT>
+    class CoreSegmentQueryProcessorBase :
+        public base::CoreSegmentQueryProcessorBase<queryTarget, _CoreSegmentT, _ResultCoreSegmentT, _ChildProcessorT>
+    {
+    protected:
+
+        using Base = base::CoreSegmentQueryProcessorBase<queryTarget, _CoreSegmentT, _ResultCoreSegmentT, _ChildProcessorT>;
+
+
+    public:
+        using CoreSegmentT = typename Base::CoreSegmentT;
+        using ProviderSegmentT = typename Base::ProviderSegmentT;
+        using ResultCoreSegmentT = typename Base::ResultCoreSegmentT;
+        using ResultProviderSegmentT = typename Base::ProviderSegmentT;
+        using ChildProcessorT = typename Base::ChildProcessorT;
+
+    public:
+        using Base::CoreSegmentQueryProcessorBase;
+        virtual ~CoreSegmentQueryProcessorBase() = default;
+
+        using Base::process;
+
+
+    };
+}
diff --git a/source/RobotAPI/libraries/armem/server/query_proc/ltm/detail/EntityQueryProcessorBase.cpp b/source/RobotAPI/libraries/armem/server/query_proc/ltm/detail/EntityQueryProcessorBase.cpp
new file mode 100644
index 000000000..e01bbbf5a
--- /dev/null
+++ b/source/RobotAPI/libraries/armem/server/query_proc/ltm/detail/EntityQueryProcessorBase.cpp
@@ -0,0 +1,9 @@
+#include "EntityQueryProcessorBase.h"
+
+#include <ArmarXCore/core/exceptions/local/ExpressionException.h>
+
+
+namespace armarx::armem::server::query_proc::base
+{
+
+}
diff --git a/source/RobotAPI/libraries/armem/server/query_proc/ltm/detail/EntityQueryProcessorBase.h b/source/RobotAPI/libraries/armem/server/query_proc/ltm/detail/EntityQueryProcessorBase.h
new file mode 100644
index 000000000..405abb2e3
--- /dev/null
+++ b/source/RobotAPI/libraries/armem/server/query_proc/ltm/detail/EntityQueryProcessorBase.h
@@ -0,0 +1,35 @@
+#pragma once
+
+#include "../../base/EntityQueryProcessorBase.h"
+
+
+namespace armarx::armem::server::query_proc::ltm::detail
+{
+
+    template <base::QueryTarget queryTarget, class _EntityT, class _ResultEntityT>
+    class EntityQueryProcessorBase :
+        public base::EntityQueryProcessorBase<queryTarget, _EntityT, _ResultEntityT>
+    {
+    protected:
+
+        using Base = base::EntityQueryProcessorBase<queryTarget, _EntityT, _ResultEntityT>;
+
+    public:
+        using EntityT = typename Base::EntityT;
+        using EntitySnapshotT = typename Base::EntitySnapshotT;
+        using ResultEntityT = typename Base::ResultEntityT;
+        using ResultSnapshotT = typename Base::EntitySnapshotT;
+
+    public:
+        virtual ~EntityQueryProcessorBase() = default;
+
+        using Base::process;
+
+
+    protected:
+        void addResultSnapshot(ResultEntityT& result, const EntitySnapshotT& snapshot) const override
+        {
+            result.addSnapshot(snapshot.loadAll());
+        }
+    };
+}
diff --git a/source/RobotAPI/libraries/armem/server/query_proc/ltm/detail/MemoryQueryProcessorBase.cpp b/source/RobotAPI/libraries/armem/server/query_proc/ltm/detail/MemoryQueryProcessorBase.cpp
new file mode 100644
index 000000000..c51a6336c
--- /dev/null
+++ b/source/RobotAPI/libraries/armem/server/query_proc/ltm/detail/MemoryQueryProcessorBase.cpp
@@ -0,0 +1 @@
+#include "MemoryQueryProcessorBase.h"
diff --git a/source/RobotAPI/libraries/armem/server/query_proc/ltm/detail/MemoryQueryProcessorBase.h b/source/RobotAPI/libraries/armem/server/query_proc/ltm/detail/MemoryQueryProcessorBase.h
new file mode 100644
index 000000000..a077de9ca
--- /dev/null
+++ b/source/RobotAPI/libraries/armem/server/query_proc/ltm/detail/MemoryQueryProcessorBase.h
@@ -0,0 +1,33 @@
+#pragma once
+
+#include "../../base/MemoryQueryProcessorBase.h"
+
+
+namespace armarx::armem::server::query_proc::ltm::detail
+{
+
+    template <base::QueryTarget queryTarget, class _MemoryT, class _ResultMemoryT, class _ChildProcessorT>
+    class MemoryQueryProcessorBase :
+        public base::MemoryQueryProcessorBase<queryTarget, _MemoryT, _ResultMemoryT, _ChildProcessorT>
+    {
+    protected:
+
+        using Base = base::MemoryQueryProcessorBase<queryTarget, _MemoryT, _ResultMemoryT, _ChildProcessorT>;
+
+    public:
+
+        using MemoryT = typename Base::MemoryT;
+        using CoreSegmentT = typename Base::CoreSegmentT;
+        using ResultMemoryT = typename Base::ResultMemoryT;
+        using ResultCoreSegmentT = typename Base::CoreSegmentT;
+        using ChildProcessorT = typename Base::ChildProcessorT;
+
+    public:
+        using Base::MemoryQueryProcessorBase;
+        virtual ~MemoryQueryProcessorBase() = default;
+
+        using Base::process;
+
+
+    };
+}
diff --git a/source/RobotAPI/libraries/armem/server/query_proc/ltm/detail/ProviderSegmentQueryProcessorBase.cpp b/source/RobotAPI/libraries/armem/server/query_proc/ltm/detail/ProviderSegmentQueryProcessorBase.cpp
new file mode 100644
index 000000000..67db9e142
--- /dev/null
+++ b/source/RobotAPI/libraries/armem/server/query_proc/ltm/detail/ProviderSegmentQueryProcessorBase.cpp
@@ -0,0 +1 @@
+#include "ProviderSegmentQueryProcessorBase.h"
diff --git a/source/RobotAPI/libraries/armem/server/query_proc/ltm/detail/ProviderSegmentQueryProcessorBase.h b/source/RobotAPI/libraries/armem/server/query_proc/ltm/detail/ProviderSegmentQueryProcessorBase.h
new file mode 100644
index 000000000..b3512921d
--- /dev/null
+++ b/source/RobotAPI/libraries/armem/server/query_proc/ltm/detail/ProviderSegmentQueryProcessorBase.h
@@ -0,0 +1,33 @@
+#pragma once
+
+#include "../../base/ProviderSegmentQueryProcessorBase.h"
+
+
+namespace armarx::armem::server::query_proc::ltm::detail
+{
+
+    template <base::QueryTarget queryTarget, class _ProviderSegmentT, class _ResultProviderSegmentT, class _ChildProcessorT>
+    class ProviderSegmentQueryProcessorBase :
+        public base::ProviderSegmentQueryProcessorBase<queryTarget, _ProviderSegmentT, _ResultProviderSegmentT, _ChildProcessorT>
+    {
+    protected:
+
+        using Base = base::ProviderSegmentQueryProcessorBase<queryTarget, _ProviderSegmentT, _ResultProviderSegmentT, _ChildProcessorT>;
+
+    public:
+
+        using ProviderSegmentT = typename Base::ProviderSegmentT;
+        using EntityT = typename Base::EntityT;
+        using ResultProviderSegmentT = typename Base::ResultProviderSegmentT;
+        using ResultEntityT = typename Base::EntityT;
+        using ChildProcessorT = typename Base::ChildProcessorT;
+
+    public:
+        using Base::ProviderSegmentQueryProcessorBase;
+        virtual ~ProviderSegmentQueryProcessorBase() = default;
+
+        using Base::process;
+
+
+    };
+}
diff --git a/source/RobotAPI/libraries/armem/server/query_proc/ltm.cpp b/source/RobotAPI/libraries/armem/server/query_proc/ltm/ltm.cpp
similarity index 100%
rename from source/RobotAPI/libraries/armem/server/query_proc/ltm.cpp
rename to source/RobotAPI/libraries/armem/server/query_proc/ltm/ltm.cpp
diff --git a/source/RobotAPI/libraries/armem/server/query_proc/ltm/ltm.h b/source/RobotAPI/libraries/armem/server/query_proc/ltm/ltm.h
new file mode 100644
index 000000000..eb8a13122
--- /dev/null
+++ b/source/RobotAPI/libraries/armem/server/query_proc/ltm/ltm.h
@@ -0,0 +1,65 @@
+#pragma once
+
+#include <RobotAPI/libraries/armem/server/ltm/disk/Memory.h>
+#include <RobotAPI/libraries/armem/server/query_proc/base.h>
+
+#include "detail/MemoryQueryProcessorBase.h"
+#include "detail/CoreSegmentQueryProcessorBase.h"
+#include "detail/ProviderSegmentQueryProcessorBase.h"
+#include "detail/EntityQueryProcessorBase.h"
+
+namespace armarx::armem::server::query_proc::ltm_server
+{
+    static const base::QueryTarget queryTarget = query::data::QueryTarget::LTM;
+
+
+    class EntityQueryProcessor :
+        public ltm::detail::EntityQueryProcessorBase<queryTarget, armem::server::ltm::disk::Entity, armem::wm::Entity>
+    {
+    protected:
+
+        using Base = ltm::detail::EntityQueryProcessorBase<queryTarget, armem::server::ltm::disk::Entity, armem::wm::Entity>;
+
+
+    public:
+
+        using Base::process;
+
+    };
+
+    class ProviderSegmentQueryProcessor :
+        public ltm::detail::ProviderSegmentQueryProcessorBase<queryTarget, armem::server::ltm::disk::ProviderSegment, armem::wm::ProviderSegment, EntityQueryProcessor>
+    {
+    protected:
+
+        using Base = ltm::detail::ProviderSegmentQueryProcessorBase<queryTarget, armem::server::ltm::disk::ProviderSegment, armem::wm::ProviderSegment, EntityQueryProcessor>;
+
+
+    public:
+        using Base::process;
+    };
+
+    class CoreSegmentQueryProcessor :
+        public ltm::detail::CoreSegmentQueryProcessorBase<queryTarget, armem::server::ltm::disk::CoreSegment, armem::wm::CoreSegment, ProviderSegmentQueryProcessor>
+    {
+    protected:
+
+        using Base = ltm::detail::CoreSegmentQueryProcessorBase<queryTarget, armem::server::ltm::disk::CoreSegment, armem::wm::CoreSegment, ProviderSegmentQueryProcessor>;
+
+
+    public:
+        using Base::process;
+    };
+
+    class MemoryQueryProcessor :
+        public ltm::detail::MemoryQueryProcessorBase<queryTarget, armem::server::ltm::disk::Memory, armem::wm::Memory, CoreSegmentQueryProcessor>
+    {
+    protected:
+
+        using Base = ltm::detail::MemoryQueryProcessorBase<queryTarget, armem::server::ltm::disk::Memory, armem::wm::Memory, CoreSegmentQueryProcessor>;
+
+    public:
+        using Base::process;
+    };
+
+}
diff --git a/source/RobotAPI/libraries/armem/server/query_proc/wm/detail/CoreSegmentQueryProcessorBase.cpp b/source/RobotAPI/libraries/armem/server/query_proc/wm/detail/CoreSegmentQueryProcessorBase.cpp
new file mode 100644
index 000000000..477263258
--- /dev/null
+++ b/source/RobotAPI/libraries/armem/server/query_proc/wm/detail/CoreSegmentQueryProcessorBase.cpp
@@ -0,0 +1,6 @@
+#include "CoreSegmentQueryProcessorBase.h"
+
+namespace armarx::armem::server::query_proc::wm::detail
+{
+
+}
diff --git a/source/RobotAPI/libraries/armem/server/query_proc/wm/detail/CoreSegmentQueryProcessorBase.h b/source/RobotAPI/libraries/armem/server/query_proc/wm/detail/CoreSegmentQueryProcessorBase.h
new file mode 100644
index 000000000..c9a0ddb51
--- /dev/null
+++ b/source/RobotAPI/libraries/armem/server/query_proc/wm/detail/CoreSegmentQueryProcessorBase.h
@@ -0,0 +1,39 @@
+#pragma once
+
+#include "../../base/CoreSegmentQueryProcessorBase.h"
+
+
+namespace armarx::armem::server::query_proc::wm::detail
+{
+
+    /**
+     * @brief Handles memory queries.
+     */
+    template <base::QueryTarget queryTarget, class _CoreSegmentT, class _ResultCoreSegmentT, class _ChildProcessorT>
+    class CoreSegmentQueryProcessorBase :
+        public base::CoreSegmentQueryProcessorBase<queryTarget, _CoreSegmentT, _ResultCoreSegmentT, _ChildProcessorT>
+    {
+    protected:
+
+        using Base = base::CoreSegmentQueryProcessorBase<queryTarget, _CoreSegmentT, _ResultCoreSegmentT, _ChildProcessorT>;
+
+
+    public:
+
+        using CoreSegmentT = typename Base::CoreSegmentT;
+        using ProviderSegmentT = typename Base::ProviderSegmentT;
+        using ResultCoreSegmentT = typename Base::ResultCoreSegmentT;
+        using ResultProviderSegmentT = typename Base::ProviderSegmentT;
+        using ChildProcessorT = typename Base::ChildProcessorT;
+
+
+    public:
+
+        using Base::CoreSegmentQueryProcessorBase;
+        virtual ~CoreSegmentQueryProcessorBase() = default;
+
+        using Base::process;
+
+
+    };
+}
diff --git a/source/RobotAPI/libraries/armem/server/query_proc/wm/detail/EntityQueryProcessorBase.cpp b/source/RobotAPI/libraries/armem/server/query_proc/wm/detail/EntityQueryProcessorBase.cpp
new file mode 100644
index 000000000..c59233630
--- /dev/null
+++ b/source/RobotAPI/libraries/armem/server/query_proc/wm/detail/EntityQueryProcessorBase.cpp
@@ -0,0 +1,9 @@
+#include "EntityQueryProcessorBase.h"
+
+#include <ArmarXCore/core/exceptions/local/ExpressionException.h>
+
+
+namespace armarx::armem::server::query_proc::wm::detail
+{
+
+}
diff --git a/source/RobotAPI/libraries/armem/server/query_proc/wm/detail/EntityQueryProcessorBase.h b/source/RobotAPI/libraries/armem/server/query_proc/wm/detail/EntityQueryProcessorBase.h
new file mode 100644
index 000000000..a107d6155
--- /dev/null
+++ b/source/RobotAPI/libraries/armem/server/query_proc/wm/detail/EntityQueryProcessorBase.h
@@ -0,0 +1,38 @@
+#pragma once
+
+#include "../../base/EntityQueryProcessorBase.h"
+
+
+namespace armarx::armem::server::query_proc::wm::detail
+{
+
+    template <base::QueryTarget queryTarget, class _EntityT, class _ResultEntityT>
+    class EntityQueryProcessorBase :
+        public base::EntityQueryProcessorBase<queryTarget, _EntityT, _ResultEntityT>
+    {
+    protected:
+
+        using Base = base::EntityQueryProcessorBase<queryTarget, _EntityT, _ResultEntityT>;
+
+
+    public:
+
+        using EntityT = typename Base::EntityT;
+        using EntitySnapshotT = typename Base::EntitySnapshotT;
+        using ResultEntityT = typename Base::ResultEntityT;
+        using ResultSnapshotT = typename Base::EntitySnapshotT;
+
+
+    public:
+        virtual ~EntityQueryProcessorBase() = default;
+
+        using Base::process;
+
+
+    protected:
+        void addResultSnapshot(ResultEntityT& result, const EntitySnapshotT& snapshot) const override
+        {
+            result.addSnapshot(snapshot);
+        }
+    };
+}
diff --git a/source/RobotAPI/libraries/armem/server/query_proc/wm/detail/MemoryQueryProcessorBase.cpp b/source/RobotAPI/libraries/armem/server/query_proc/wm/detail/MemoryQueryProcessorBase.cpp
new file mode 100644
index 000000000..f72b60033
--- /dev/null
+++ b/source/RobotAPI/libraries/armem/server/query_proc/wm/detail/MemoryQueryProcessorBase.cpp
@@ -0,0 +1,7 @@
+#include "MemoryQueryProcessorBase.h"
+
+
+namespace armarx::armem::server::query_proc::wm::detail
+{
+
+}
diff --git a/source/RobotAPI/libraries/armem/server/query_proc/wm/detail/MemoryQueryProcessorBase.h b/source/RobotAPI/libraries/armem/server/query_proc/wm/detail/MemoryQueryProcessorBase.h
new file mode 100644
index 000000000..38d7a9ec4
--- /dev/null
+++ b/source/RobotAPI/libraries/armem/server/query_proc/wm/detail/MemoryQueryProcessorBase.h
@@ -0,0 +1,35 @@
+#pragma once
+
+#include "../../base/MemoryQueryProcessorBase.h"
+
+
+namespace armarx::armem::server::query_proc::wm::detail
+{
+
+    template <base::QueryTarget queryTarget, class _MemoryT, class _ResultMemoryT, class _ChildProcessorT>
+    class MemoryQueryProcessorBase :
+        public base::MemoryQueryProcessorBase<queryTarget, _MemoryT, _ResultMemoryT, _ChildProcessorT>
+    {
+    protected:
+
+        using Base = base::MemoryQueryProcessorBase<queryTarget, _MemoryT, _ResultMemoryT, _ChildProcessorT>;
+
+
+    public:
+
+        using MemoryT = typename Base::MemoryT;
+        using CoreSegmentT = typename Base::CoreSegmentT;
+        using ResultMemoryT = typename Base::ResultMemoryT;
+        using ResultCoreSegmentT = typename Base::CoreSegmentT;
+        using ChildProcessorT = typename Base::ChildProcessorT;
+
+
+    public:
+        using Base::MemoryQueryProcessorBase;
+        virtual ~MemoryQueryProcessorBase() = default;
+
+        using Base::process;
+
+
+    };
+}
diff --git a/source/RobotAPI/libraries/armem/server/query_proc/wm/detail/ProviderSegmentQueryProcessorBase.cpp b/source/RobotAPI/libraries/armem/server/query_proc/wm/detail/ProviderSegmentQueryProcessorBase.cpp
new file mode 100644
index 000000000..d11b94bcd
--- /dev/null
+++ b/source/RobotAPI/libraries/armem/server/query_proc/wm/detail/ProviderSegmentQueryProcessorBase.cpp
@@ -0,0 +1,6 @@
+#include "ProviderSegmentQueryProcessorBase.h"
+
+namespace armarx::armem::server::query_proc::wm::detail
+{
+
+}
diff --git a/source/RobotAPI/libraries/armem/server/query_proc/wm/detail/ProviderSegmentQueryProcessorBase.h b/source/RobotAPI/libraries/armem/server/query_proc/wm/detail/ProviderSegmentQueryProcessorBase.h
new file mode 100644
index 000000000..759938b2b
--- /dev/null
+++ b/source/RobotAPI/libraries/armem/server/query_proc/wm/detail/ProviderSegmentQueryProcessorBase.h
@@ -0,0 +1,35 @@
+#pragma once
+
+#include "../../base/ProviderSegmentQueryProcessorBase.h"
+
+
+namespace armarx::armem::server::query_proc::wm::detail
+{
+
+    template <base::QueryTarget queryTarget, class _ProviderSegmentT, class _ResultProviderSegmentT, class _ChildProcessorT>
+    class ProviderSegmentQueryProcessorBase :
+        public base::ProviderSegmentQueryProcessorBase<queryTarget, _ProviderSegmentT, _ResultProviderSegmentT, _ChildProcessorT>
+    {
+    protected:
+
+        using Base = base::ProviderSegmentQueryProcessorBase<queryTarget, _ProviderSegmentT, _ResultProviderSegmentT, _ChildProcessorT>;
+
+
+    public:
+
+        using ProviderSegmentT = typename Base::ProviderSegmentT;
+        using EntityT = typename Base::EntityT;
+        using ResultProviderSegmentT = typename Base::ResultProviderSegmentT;
+        using ResultEntityT = typename Base::EntityT;
+        using ChildProcessorT = typename Base::ChildProcessorT;
+
+
+    public:
+        using Base::ProviderSegmentQueryProcessorBase;
+        virtual ~ProviderSegmentQueryProcessorBase() = default;
+
+        using Base::process;
+
+
+    };
+}
diff --git a/source/RobotAPI/libraries/armem/server/query_proc/wm.cpp b/source/RobotAPI/libraries/armem/server/query_proc/wm/wm.cpp
similarity index 89%
rename from source/RobotAPI/libraries/armem/server/query_proc/wm.cpp
rename to source/RobotAPI/libraries/armem/server/query_proc/wm/wm.cpp
index 0ace705be..b8d25db27 100644
--- a/source/RobotAPI/libraries/armem/server/query_proc/wm.cpp
+++ b/source/RobotAPI/libraries/armem/server/query_proc/wm/wm.cpp
@@ -16,7 +16,8 @@ namespace armarx::armem::server::query_proc::wm
 {
 
     ProviderSegmentQueryProcessor::ProviderSegmentQueryProcessor(DataMode dataMode) :
-        ProviderSegmentQueryProcessorBase(dataMode), HasDataMode(dataMode)
+        detail::ProviderSegmentQueryProcessorBase<queryTarget, armem::wm::ProviderSegment, armem::wm::ProviderSegment, EntityQueryProcessor>(dataMode),
+        HasDataMode(dataMode)
     {
     }
 
diff --git a/source/RobotAPI/libraries/armem/server/query_proc/wm.h b/source/RobotAPI/libraries/armem/server/query_proc/wm/wm.h
similarity index 54%
rename from source/RobotAPI/libraries/armem/server/query_proc/wm.h
rename to source/RobotAPI/libraries/armem/server/query_proc/wm/wm.h
index aa52b4ab2..2d1ff3e35 100644
--- a/source/RobotAPI/libraries/armem/server/query_proc/wm.h
+++ b/source/RobotAPI/libraries/armem/server/query_proc/wm/wm.h
@@ -3,7 +3,11 @@
 #include <RobotAPI/libraries/armem/core/DataMode.h>
 #include <RobotAPI/libraries/armem/core/wm/memory_definitions.h>
 #include <RobotAPI/libraries/armem/server/wm/memory_definitions.h>
-#include <RobotAPI/libraries/armem/server/query_proc/base.h>
+
+#include "detail/MemoryQueryProcessorBase.h"
+#include "detail/CoreSegmentQueryProcessorBase.h"
+#include "detail/ProviderSegmentQueryProcessorBase.h"
+#include "detail/EntityQueryProcessorBase.h"
 
 
 namespace armarx::armem::server::query_proc::wm
@@ -30,15 +34,22 @@ namespace armarx::armem::server::query_proc::wm::detail
 
     template <class SourceEntityT>
     class EntityQueryProcessor :
-        public base::EntityQueryProcessorBase<queryTarget, SourceEntityT, armem::wm::Entity>,
+        public EntityQueryProcessorBase<queryTarget, SourceEntityT, armem::wm::Entity>,
         public HasDataMode
     {
+    protected:
+
+        using Base = EntityQueryProcessorBase<queryTarget, SourceEntityT, armem::wm::Entity>;
+        using Entity = armem::wm::Entity;
+
+
     public:
 
         EntityQueryProcessor(DataMode dataMode = DataMode::WithData) :
             HasDataMode(dataMode)
         {}
 
+        using Base::process;
 
     protected:
 
@@ -70,41 +81,62 @@ namespace armarx::armem::server::query_proc::wm
 
     using EntityQueryProcessor = detail::EntityQueryProcessor<armem::wm::Entity>;
 
-
     class ProviderSegmentQueryProcessor :
-        public base::ProviderSegmentQueryProcessorBase<queryTarget, armem::wm::ProviderSegment, armem::wm::ProviderSegment, EntityQueryProcessor >,
+        public detail::ProviderSegmentQueryProcessorBase<queryTarget, armem::wm::ProviderSegment, armem::wm::ProviderSegment, EntityQueryProcessor>,
         public detail::HasDataMode
     {
+    protected:
+
+        using Base = detail::ProviderSegmentQueryProcessorBase<queryTarget, armem::wm::ProviderSegment, armem::wm::ProviderSegment, EntityQueryProcessor>;
+        using ProviderSegment = armem::wm::ProviderSegment;
+        using Entity = armem::wm::Entity;
+
+
     public:
 
         ProviderSegmentQueryProcessor(DataMode dataMode = DataMode::WithData);
 
+        using Base::process;
     };
 
 
     class CoreSegmentQueryProcessor :
-        public base::CoreSegmentQueryProcessorBase <queryTarget, armem::wm::CoreSegment, armem::wm::CoreSegment, ProviderSegmentQueryProcessor >,
+        public detail::CoreSegmentQueryProcessorBase <queryTarget, armem::wm::CoreSegment, armem::wm::CoreSegment, ProviderSegmentQueryProcessor>,
         public detail::HasDataMode
     {
-        using Base = base::CoreSegmentQueryProcessorBase<queryTarget, armem::wm::CoreSegment, armem::wm::CoreSegment, ProviderSegmentQueryProcessor>;
+    protected:
+
+        using Base = wm::detail::CoreSegmentQueryProcessorBase<queryTarget, armem::wm::CoreSegment, armem::wm::CoreSegment, ProviderSegmentQueryProcessor>;
         using CoreSegment = armem::wm::CoreSegment;
         using ProviderSegment = armem::wm::ProviderSegment;
 
+
     public:
 
         CoreSegmentQueryProcessor(DataMode dataMode = DataMode::WithData);
 
+        using Base::process;
+
     };
 
 
     class MemoryQueryProcessor :
-        public base::MemoryQueryProcessorBase<queryTarget, armem::wm::Memory, armem::wm::Memory, CoreSegmentQueryProcessor>,
+        public detail::MemoryQueryProcessorBase<queryTarget, armem::wm::Memory, armem::wm::Memory, CoreSegmentQueryProcessor>,
         public detail::HasDataMode
     {
+    protected:
+
+        using Base = detail::MemoryQueryProcessorBase<queryTarget, armem::wm::Memory, armem::wm::Memory, CoreSegmentQueryProcessor>;
+        using Memory = armem::wm::Memory;
+        using CoreSegment = armem::wm::CoreSegment;
+
+
     public:
 
         MemoryQueryProcessor(DataMode dataMode = DataMode::WithData);
 
+        using Base::process;
+
     };
 
 }
@@ -117,9 +149,15 @@ namespace armarx::armem::server::query_proc::wm_server
 
 
     class ProviderSegmentQueryProcessor :
-        public base::ProviderSegmentQueryProcessorBase<wm::queryTarget, server::wm::ProviderSegment, armem::wm::ProviderSegment, EntityQueryProcessor >,
+        public wm::detail::ProviderSegmentQueryProcessorBase<wm::queryTarget, server::wm::ProviderSegment, armem::wm::ProviderSegment, EntityQueryProcessor>,
         public wm::detail::HasDataMode
     {
+    protected:
+
+        using Base = wm::detail::ProviderSegmentQueryProcessorBase<wm::queryTarget, server::wm::ProviderSegment, armem::wm::ProviderSegment, EntityQueryProcessor>;
+        using ProviderSegment = server::wm::ProviderSegment;
+        using Entity = server::wm::Entity;
+
     public:
 
         ProviderSegmentQueryProcessor(DataMode dataMode = DataMode::WithData);
@@ -128,18 +166,20 @@ namespace armarx::armem::server::query_proc::wm_server
 
 
     class CoreSegmentQueryProcessor :
-        public base::CoreSegmentQueryProcessorBase <wm::queryTarget, server::wm::CoreSegment, armem::wm::CoreSegment, ProviderSegmentQueryProcessor >,
+        public wm::detail::CoreSegmentQueryProcessorBase <wm::queryTarget, server::wm::CoreSegment, armem::wm::CoreSegment, ProviderSegmentQueryProcessor>,
         public wm::detail::HasDataMode
     {
-        using Base = base::CoreSegmentQueryProcessorBase<wm::queryTarget, server::wm::CoreSegment, armem::wm::CoreSegment, ProviderSegmentQueryProcessor>;
+    protected:
+
+        using Base = wm::detail::CoreSegmentQueryProcessorBase<wm::queryTarget, server::wm::CoreSegment, armem::wm::CoreSegment, ProviderSegmentQueryProcessor>;
         using CoreSegment = server::wm::CoreSegment;
         using ProviderSegment = server::wm::ProviderSegment;
 
+
     public:
 
         CoreSegmentQueryProcessor(DataMode dataMode = DataMode::WithData);
 
-
         using Base::process;
 
         /// Locks the core segment, then delegates back to `CoreSegmentQueryProcessorBase`.
@@ -152,13 +192,21 @@ namespace armarx::armem::server::query_proc::wm_server
 
 
     class MemoryQueryProcessor :
-        public base::MemoryQueryProcessorBase<wm::queryTarget, server::wm::Memory, armem::wm::Memory, CoreSegmentQueryProcessor>,
+        public wm::detail::MemoryQueryProcessorBase<wm::queryTarget, server::wm::Memory, armem::wm::Memory, CoreSegmentQueryProcessor>,
         public wm::detail::HasDataMode
     {
+    protected:
+
+        using Base = wm::detail::MemoryQueryProcessorBase<wm::queryTarget, server::wm::Memory, armem::wm::Memory, CoreSegmentQueryProcessor>;
+        using Memory = server::wm::Memory;
+        using CoreSegment = server::wm::CoreSegment;
+
     public:
 
         MemoryQueryProcessor(DataMode dataMode = DataMode::WithData);
 
+        using Base::process;
+
     };
 
 }
diff --git a/source/RobotAPI/libraries/armem/test/ArMemLTMBenchmark.cpp b/source/RobotAPI/libraries/armem/test/ArMemLTMBenchmark.cpp
new file mode 100644
index 000000000..a5d1b1a81
--- /dev/null
+++ b/source/RobotAPI/libraries/armem/test/ArMemLTMBenchmark.cpp
@@ -0,0 +1,118 @@
+/*
+ * This file is part of ArmarX.
+ *
+ * ArmarX is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * ArmarX is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * @package    RobotAPI::ArmarXObjects::armem
+ * @author     Simon Ottenhaus ( simon dot ottenhaus at kit dot edu )
+ * @date       2020
+ * @copyright  http://www.gnu.org/licenses/gpl-2.0.txt
+ *             GNU General Public License
+ */
+
+#define BOOST_TEST_MODULE RobotAPI::ArmarXLibraries::armem
+
+#define ARMARX_BOOST_TEST
+
+#include <RobotAPI/Test.h>
+#include <RobotAPI/libraries/armem/server/ltm/disk/Memory.h>
+#include <RobotAPI/libraries/armem/core/error.h>
+
+#include <RobotAPI/libraries/aron/core/data/variant/All.h>
+#include <RobotAPI/libraries/aron/core/type/variant/All.h>
+
+#include <ArmarXCore/core/time/StopWatch.h>
+
+
+#include <filesystem>
+#include <iostream>
+
+namespace armem = armarx::armem;
+namespace aron = armarx::aron;
+namespace fs = std::filesystem;
+
+namespace ArMemLTMBenchmark
+{
+    struct Fixture
+    {
+        fs::path storagePath = "/tmp/TestMemoryExport";
+
+        Fixture()
+        {
+            clearStoragePath();
+        }
+        ~Fixture()
+        {
+            //clearStoragePath();
+        }
+
+        void clearStoragePath()
+        {
+            if (fs::exists(storagePath))
+            {
+                fs::remove_all(storagePath);
+            }
+            BOOST_TEST_INFO("Storage path: " << storagePath);
+            BOOST_REQUIRE(!fs::exists(storagePath));
+        }
+
+        void run(const std::string& memoryName, const std::string& memberNamePrefix)
+        {
+
+        }
+    };
+}
+
+BOOST_FIXTURE_TEST_SUITE(ArMemLTMBenchmark, Fixture)
+
+
+BOOST_AUTO_TEST_CASE(test_memory_export__benchmark)
+{
+    int num_exports = 10;
+    armem::server::ltm::disk::Memory ltm;
+    ltm.setMemoryID(ltm.id().withMemoryName("Test"));
+
+    auto data = std::make_shared<aron::data::Dict>();
+    //auto member1 = std::make_shared<aron::data::Int>(42);
+    //auto member2 = std::make_shared<aron::data::String>("Hallo Welt");
+    //data->addElement("Member1", member1);
+    //data->addElement("Member2", member2);
+
+    std::vector<int> dimensions = {1280, 720, 3};
+    std::string type = "0";
+    std::vector<unsigned char> d(1280*720*3, 0);
+    data->addElement("image", std::make_shared<aron::data::NDArray>(dimensions, type, d));
+
+    armem::wm::Memory wm("Test");
+    auto& core = wm.addCoreSegment("CoreS");
+    auto& prov = core.addProviderSegment("ProvS");
+    auto& en = prov.addEntity("EntityS");
+
+    TIMING_START(LTM_Export__Benchmark);
+
+    for (unsigned int i = 0; i < num_exports; ++i)
+    {
+        en.clear();
+        auto& snap = en.addSnapshot(IceUtil::Time::now());
+        auto& ins = snap.addInstance();
+        ins.data() = data;
+
+        ltm.append(wm);
+        ltm.storeBuffer();
+    }
+
+    TIMING_END(LTM_Export__Benchmark);
+}
+
+BOOST_AUTO_TEST_SUITE_END()
+
diff --git a/source/RobotAPI/libraries/armem/test/ArMemQueryTest.cpp b/source/RobotAPI/libraries/armem/test/ArMemQueryTest.cpp
index 13d050572..191cfb625 100644
--- a/source/RobotAPI/libraries/armem/test/ArMemQueryTest.cpp
+++ b/source/RobotAPI/libraries/armem/test/ArMemQueryTest.cpp
@@ -28,7 +28,7 @@
 #include <RobotAPI/interface/armem/query.h>
 #include <RobotAPI/libraries/armem/core/error.h>
 #include <RobotAPI/libraries/armem/core/base/detail/negative_index_semantics.h>
-#include <RobotAPI/libraries/armem/server/query_proc/wm.h>
+#include <RobotAPI/libraries/armem/server/query_proc/wm/wm.h>
 
 #include <ArmarXCore/core/exceptions/LocalException.h>
 
diff --git a/source/RobotAPI/libraries/armem/test/CMakeLists.txt b/source/RobotAPI/libraries/armem/test/CMakeLists.txt
index 43b756504..a80618cee 100644
--- a/source/RobotAPI/libraries/armem/test/CMakeLists.txt
+++ b/source/RobotAPI/libraries/armem/test/CMakeLists.txt
@@ -6,6 +6,7 @@ armarx_add_test(ArMemForEachTest ArMemForEachTest.cpp "${LIBS}")
 armarx_add_test(ArMemGetFindTest ArMemGetFindTest.cpp "${LIBS}")
 armarx_add_test(ArMemIceConversionsTest ArMemIceConversionsTest.cpp "${LIBS}")
 armarx_add_test(ArMemLTMTest ArMemLTMTest.cpp "${LIBS}")
+armarx_add_test(ArMemLTMBenchmark ArMemLTMBenchmark.cpp "${LIBS}")
 armarx_add_test(ArMemMemoryTest ArMemMemoryTest.cpp "${LIBS}")
 armarx_add_test(ArMemMemoryIDTest ArMemMemoryIDTest.cpp "${LIBS}")
 armarx_add_test(ArMemQueryBuilderTest ArMemQueryBuilderTest.cpp "${LIBS}")
diff --git a/source/RobotAPI/libraries/armem_gui/MemoryViewer.cpp b/source/RobotAPI/libraries/armem_gui/MemoryViewer.cpp
index 54dc9f56f..9ce928459 100644
--- a/source/RobotAPI/libraries/armem_gui/MemoryViewer.cpp
+++ b/source/RobotAPI/libraries/armem_gui/MemoryViewer.cpp
@@ -3,8 +3,8 @@
 #include <RobotAPI/libraries/armem/core/wm/ice_conversions.h>
 #include <RobotAPI/libraries/armem_gui/gui_utils.h>
 
-#include <RobotAPI/libraries/armem/server/query_proc/wm.h>
-#include <RobotAPI/libraries/armem/server/query_proc/ltm.h>
+#include <RobotAPI/libraries/armem/server/query_proc/wm/wm.h>
+#include <RobotAPI/libraries/armem/server/query_proc/ltm/ltm.h>
 
 #include <ArmarXGui/libraries/SimpleConfigDialog/SimpleConfigDialog.h>
 
@@ -185,7 +185,7 @@ namespace armarx::armem::gui
 
     void MemoryViewer::storeInLTM()
     {
-        TIMING_START(MemoryStore)
+        TIMING_START(MemoryStore);
 
         for (auto& [name, reader] : memoryReaders)
         {
@@ -194,7 +194,7 @@ namespace armarx::armem::gui
             reader.readAndStore(input);
         }
 
-        TIMING_END_STREAM(MemoryStore, ARMARX_VERBOSE)
+        TIMING_END_STREAM(MemoryStore, ARMARX_VERBOSE);
     }
 
 
diff --git a/source/RobotAPI/libraries/armem_gui/disk/ControlWidget.cpp b/source/RobotAPI/libraries/armem_gui/disk/ControlWidget.cpp
index 406dcfdf6..0e0f620d2 100644
--- a/source/RobotAPI/libraries/armem_gui/disk/ControlWidget.cpp
+++ b/source/RobotAPI/libraries/armem_gui/disk/ControlWidget.cpp
@@ -1,8 +1,7 @@
 #include "ControlWidget.h"
 
-#include <RobotAPI/libraries/armem/server/ltm/disk/MemoryManager.h>
-#include <RobotAPI/libraries/armem/server/ltm/disk/operations.h>
-#include <RobotAPI/libraries/armem/server/query_proc/ltm.h>
+#include <RobotAPI/libraries/armem/server/ltm/disk/Memory.h>
+#include <RobotAPI/libraries/armem/server/query_proc/ltm/ltm.h>
 
 #include <ArmarXCore/core/exceptions/local/ExpressionException.h>
 
@@ -103,9 +102,9 @@ namespace armarx::armem::gui::disk
                 {
                     std::filesystem::create_directories(path / name);
 
-                    armem::server::ltm::disk::Memory manager((path / name));
-                    manager.reload();
-                    manager.append(data);
+                    armem::server::ltm::disk::Memory memory((path / name));
+                    memory.append(data);
+                    memory.storeBuffer();
 
                     numStored++;
                 }
@@ -147,11 +146,9 @@ namespace armarx::armem::gui::disk
             {
                 if (dir.is_directory())
                 {
-                    std::string memoryName = dir.path().filename();
                     armem::server::ltm::disk::Memory ltm(dir.path());
-                    ltm.reload();
-                    armem::wm::Memory memory = ltm.convert();
-                    memoryData[memoryName] = std::move(memory);
+                    armem::wm::Memory memory = ltm.loadAll();
+                    memoryData[memory.name()] = std::move(memory);
 
                     numLoaded++;
                 }
-- 
GitLab