start with messages (no fragments get created yet)
This commit is contained in:
parent
e67d7d37b5
commit
2bc30ffcdc
@ -19,6 +19,18 @@ target_link_libraries(fragment_store PUBLIC
|
|||||||
|
|
||||||
########################################
|
########################################
|
||||||
|
|
||||||
|
add_library(message_fragment_store
|
||||||
|
./fragment_store/message_fragment_store.hpp
|
||||||
|
./fragment_store/message_fragment_store.cpp
|
||||||
|
)
|
||||||
|
target_compile_features(message_fragment_store PRIVATE cxx_std_20)
|
||||||
|
target_link_libraries(message_fragment_store PUBLIC
|
||||||
|
fragment_store
|
||||||
|
solanaceae_message3
|
||||||
|
)
|
||||||
|
|
||||||
|
########################################
|
||||||
|
|
||||||
add_executable(fragment_store_test
|
add_executable(fragment_store_test
|
||||||
fragment_store/test_fragstore.cpp
|
fragment_store/test_fragstore.cpp
|
||||||
)
|
)
|
||||||
@ -112,6 +124,7 @@ target_link_libraries(tomato PUBLIC
|
|||||||
solanaceae_tox_messages
|
solanaceae_tox_messages
|
||||||
|
|
||||||
fragment_store
|
fragment_store
|
||||||
|
message_fragment_store
|
||||||
|
|
||||||
SDL3::SDL3
|
SDL3::SDL3
|
||||||
|
|
||||||
|
131
src/fragment_store/message_fragment_store.cpp
Normal file
131
src/fragment_store/message_fragment_store.cpp
Normal file
@ -0,0 +1,131 @@
|
|||||||
|
#include "./message_fragment_store.hpp"
|
||||||
|
|
||||||
|
#include <solanaceae/message3/components.hpp>
|
||||||
|
|
||||||
|
#include <nlohmann/json.hpp>
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
#include <cassert>
|
||||||
|
|
||||||
|
static bool serl_json_msg_ts_range(void* comp, nlohmann::json& out) {
|
||||||
|
if (comp == nullptr) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
out = nlohmann::json::object();
|
||||||
|
|
||||||
|
auto& r_comp = *reinterpret_cast<FragComp::MessagesTSRange*>(comp);
|
||||||
|
|
||||||
|
out["begin"] = r_comp.begin;
|
||||||
|
out["end"] = r_comp.end;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MessageFragmentStore::handleMessage(const Message3Handle& m) {
|
||||||
|
if (!static_cast<bool>(m)) {
|
||||||
|
return; // huh?
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!m.all_of<Message::Components::Timestamp>()) {
|
||||||
|
return; // we only handle msg with ts
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto msg_ts = m.get<Message::Components::Timestamp>().ts;
|
||||||
|
|
||||||
|
if (!m.all_of<Message::Components::FUID>()) {
|
||||||
|
// missing fuid
|
||||||
|
// find closesed non-sealed off fragment
|
||||||
|
|
||||||
|
std::vector<uint8_t> fragment_uid;
|
||||||
|
|
||||||
|
// first search for fragment where the ts falls into the range
|
||||||
|
for (const auto& [tsrage, fid] : _fuid_open) {
|
||||||
|
if (tsrage.ts_begin <= msg_ts && tsrage.ts_end >= msg_ts) {
|
||||||
|
fragment_uid = fid;
|
||||||
|
// TODO: check conditions for open here
|
||||||
|
// TODO: mark msg (and frag?) dirty
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// if it did not fit into an existing fragment, we next look for fragments that could be extended
|
||||||
|
if (fragment_uid.empty()) {
|
||||||
|
for (const auto& [tsrage, fid] : _fuid_open) {
|
||||||
|
const int64_t frag_range = int64_t(tsrage.ts_end) - int64_t(tsrage.ts_begin);
|
||||||
|
//constexpr static int64_t max_frag_ts_extent {1000*60*60};
|
||||||
|
constexpr static int64_t max_frag_ts_extent {1000*60*3}; // 3min for testing
|
||||||
|
const int64_t possible_extention = max_frag_ts_extent - frag_range;
|
||||||
|
|
||||||
|
// which direction
|
||||||
|
if ((tsrage.ts_begin - possible_extention) <= msg_ts) {
|
||||||
|
fragment_uid = fid;
|
||||||
|
auto fh = _fs.fragmentHandle(_fs.getFragmentByID(fid));
|
||||||
|
assert(static_cast<bool>(fh));
|
||||||
|
|
||||||
|
// assuming ts range exists
|
||||||
|
auto& fts_comp = fh.get<FragComp::MessagesTSRange>();
|
||||||
|
fts_comp.begin = msg_ts; // extend into the past
|
||||||
|
|
||||||
|
// TODO: check conditions for open here
|
||||||
|
// TODO: mark msg (and frag?) dirty
|
||||||
|
} else if ((tsrage.ts_end + possible_extention) >= msg_ts) {
|
||||||
|
fragment_uid = fid;
|
||||||
|
auto fh = _fs.fragmentHandle(_fs.getFragmentByID(fid));
|
||||||
|
assert(static_cast<bool>(fh));
|
||||||
|
|
||||||
|
// assuming ts range exists
|
||||||
|
auto& fts_comp = fh.get<FragComp::MessagesTSRange>();
|
||||||
|
fts_comp.end = msg_ts; // extend into the future
|
||||||
|
|
||||||
|
// TODO: check conditions for open here
|
||||||
|
// TODO: mark msg (and frag?) dirty
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// if its still not found, we need a new fragment
|
||||||
|
if (fragment_uid.empty()) {
|
||||||
|
}
|
||||||
|
|
||||||
|
// if this is still empty, something is very wrong and we exit here
|
||||||
|
if (fragment_uid.empty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
m.emplace<Message::Components::FUID>(fragment_uid);
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: do we use fid?
|
||||||
|
|
||||||
|
// on new message: assign fuid
|
||||||
|
// on new and update: mark as fragment dirty
|
||||||
|
}
|
||||||
|
|
||||||
|
MessageFragmentStore::MessageFragmentStore(
|
||||||
|
RegistryMessageModel& rmm,
|
||||||
|
FragmentStore& fs
|
||||||
|
) : _rmm(rmm), _fs(fs) {
|
||||||
|
_rmm.subscribe(this, RegistryMessageModel_Event::message_construct);
|
||||||
|
_rmm.subscribe(this, RegistryMessageModel_Event::message_updated);
|
||||||
|
_rmm.subscribe(this, RegistryMessageModel_Event::message_destroy);
|
||||||
|
|
||||||
|
_fs._sc.registerSerializerJson<FragComp::MessagesTSRange>(serl_json_msg_ts_range);
|
||||||
|
}
|
||||||
|
|
||||||
|
MessageFragmentStore::~MessageFragmentStore(void) {
|
||||||
|
}
|
||||||
|
|
||||||
|
float MessageFragmentStore::tick(float time_delta) {
|
||||||
|
return 1000.f*60.f*60.f;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MessageFragmentStore::onEvent(const Message::Events::MessageConstruct& e) {
|
||||||
|
handleMessage(e.e);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MessageFragmentStore::onEvent(const Message::Events::MessageUpdated& e) {
|
||||||
|
handleMessage(e.e);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
66
src/fragment_store/message_fragment_store.hpp
Normal file
66
src/fragment_store/message_fragment_store.hpp
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "./meta_components.hpp"
|
||||||
|
#include "./fragment_store_i.hpp"
|
||||||
|
#include "./fragment_store.hpp"
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
#include <entt/entity/registry.hpp>
|
||||||
|
#include <entt/container/dense_map.hpp>
|
||||||
|
|
||||||
|
#include <solanaceae/message3/registry_message_model.hpp>
|
||||||
|
|
||||||
|
#include <map>
|
||||||
|
|
||||||
|
namespace Message::Components {
|
||||||
|
|
||||||
|
using FUID = FragComp::ID;
|
||||||
|
|
||||||
|
struct FID {
|
||||||
|
FragmentID fid {entt::null};
|
||||||
|
};
|
||||||
|
|
||||||
|
} // Message::Components
|
||||||
|
|
||||||
|
namespace Fragment::Components {
|
||||||
|
struct MessagesTSRange {
|
||||||
|
// timestamp range within the fragment
|
||||||
|
uint64_t begin {0};
|
||||||
|
uint64_t end {0};
|
||||||
|
};
|
||||||
|
} // Fragment::Components
|
||||||
|
|
||||||
|
// handles fragments for messages
|
||||||
|
// on new message: assign fuid
|
||||||
|
// on new and update: mark as fragment dirty
|
||||||
|
// on delete: mark as fragment dirty?
|
||||||
|
class MessageFragmentStore : public RegistryMessageModelEventI {
|
||||||
|
protected:
|
||||||
|
RegistryMessageModel& _rmm;
|
||||||
|
FragmentStore& _fs;
|
||||||
|
|
||||||
|
void handleMessage(const Message3Handle& m);
|
||||||
|
|
||||||
|
struct TSRange final {
|
||||||
|
uint64_t ts_begin {0};
|
||||||
|
uint64_t ts_end {0};
|
||||||
|
};
|
||||||
|
// only contains fragments with <1024 messages and <28h tsrage
|
||||||
|
std::map<TSRange, std::vector<uint8_t>> _fuid_open;
|
||||||
|
|
||||||
|
std::map<uint64_t, std::vector<uint8_t>> _fuid_save_queue;
|
||||||
|
|
||||||
|
public:
|
||||||
|
MessageFragmentStore(
|
||||||
|
RegistryMessageModel& rmm,
|
||||||
|
FragmentStore& fs
|
||||||
|
);
|
||||||
|
virtual ~MessageFragmentStore(void);
|
||||||
|
|
||||||
|
float tick(float time_delta);
|
||||||
|
|
||||||
|
protected: // rmm
|
||||||
|
bool onEvent(const Message::Events::MessageConstruct& e) override;
|
||||||
|
bool onEvent(const Message::Events::MessageUpdated& e) override;
|
||||||
|
};
|
||||||
|
|
@ -14,6 +14,7 @@ MainScreen::MainScreen(SDL_Renderer* renderer_, std::string save_path, std::stri
|
|||||||
renderer(renderer_),
|
renderer(renderer_),
|
||||||
rmm(cr),
|
rmm(cr),
|
||||||
mts(rmm),
|
mts(rmm),
|
||||||
|
mfs(rmm, fs),
|
||||||
tc(save_path, save_password),
|
tc(save_path, save_password),
|
||||||
tpi(tc.getTox()),
|
tpi(tc.getTox()),
|
||||||
ad(tc),
|
ad(tc),
|
||||||
|
@ -7,6 +7,7 @@
|
|||||||
#include <solanaceae/contact/contact_model3.hpp>
|
#include <solanaceae/contact/contact_model3.hpp>
|
||||||
#include <solanaceae/message3/registry_message_model.hpp>
|
#include <solanaceae/message3/registry_message_model.hpp>
|
||||||
#include <solanaceae/message3/message_time_sort.hpp>
|
#include <solanaceae/message3/message_time_sort.hpp>
|
||||||
|
#include "./fragment_store/message_fragment_store.hpp"
|
||||||
#include <solanaceae/plugin/plugin_manager.hpp>
|
#include <solanaceae/plugin/plugin_manager.hpp>
|
||||||
#include <solanaceae/toxcore/tox_event_logger.hpp>
|
#include <solanaceae/toxcore/tox_event_logger.hpp>
|
||||||
#include "./tox_private_impl.hpp"
|
#include "./tox_private_impl.hpp"
|
||||||
@ -50,6 +51,7 @@ struct MainScreen final : public Screen {
|
|||||||
Contact3Registry cr;
|
Contact3Registry cr;
|
||||||
RegistryMessageModel rmm;
|
RegistryMessageModel rmm;
|
||||||
MessageTimeSort mts;
|
MessageTimeSort mts;
|
||||||
|
MessageFragmentStore mfs;
|
||||||
|
|
||||||
ToxEventLogger tel{std::cout};
|
ToxEventLogger tel{std::cout};
|
||||||
ToxClient tc;
|
ToxClient tc;
|
||||||
|
Loading…
Reference in New Issue
Block a user