From f4c0993bff2b2de75176cfc019e7cc8e2e5d3c49 Mon Sep 17 00:00:00 2001 From: Ivan Baidakou Date: Sat, 13 Dec 2025 16:20:23 +0300 Subject: [PATCH] core: refactor remote_folder_info -> remove_view --- CMakeLists.txt | 4 +- src/model/device.h | 6 +- src/model/diff/cluster_visitor.cpp | 12 ++-- src/model/diff/cluster_visitor.h | 2 +- src/model/diff/diffs_fwd.h | 2 +- .../diff/modify/add_remote_folder_infos.cpp | 50 ---------------- src/model/diff/modify/share_folder.cpp | 6 -- src/model/diff/modify/upsert_folder.h | 1 + src/model/diff/peer/cluster_update.cpp | 23 ++++---- src/model/diff/peer/update_remote_views.cpp | 41 +++++++++++++ .../update_remote_views.h} | 16 +++--- src/model/misc/updates_streamer.cpp | 20 ++++--- src/model/misc/updates_streamer.h | 3 +- src/model/remote_folder_info.cpp | 39 ------------- src/model/remote_folder_info.h | 55 ------------------ src/model/remote_view.cpp | 37 ++++++++++++ src/model/remote_view.h | 57 +++++++++++++++++++ src/net/controller_actor.cpp | 10 ++-- src/net/local_keeper/child_info.h | 1 + src/presentation/folder_entity.h | 1 + src/presentation/folder_presence.h | 1 + tests/031-diff-cluster_update.cpp | 23 +++++--- tests/054-updates_streamer.cpp | 4 +- 23 files changed, 208 insertions(+), 206 deletions(-) delete mode 100644 src/model/diff/modify/add_remote_folder_infos.cpp create mode 100644 src/model/diff/peer/update_remote_views.cpp rename src/model/diff/{modify/add_remote_folder_infos.h => peer/update_remote_views.h} (58%) delete mode 100644 src/model/remote_folder_info.cpp delete mode 100644 src/model/remote_folder_info.h create mode 100644 src/model/remote_view.cpp create mode 100644 src/model/remote_view.h diff --git a/CMakeLists.txt b/CMakeLists.txt index cef83b75..2f28c1c7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -151,7 +151,6 @@ add_library(syncspirit_core src/model/diff/local/synchronization_finish.cpp src/model/diff/local/synchronization_start.cpp src/model/diff/modify/add_blocks.cpp - src/model/diff/modify/add_remote_folder_infos.cpp src/model/diff/modify/add_ignored_device.cpp src/model/diff/modify/add_pending_device.cpp src/model/diff/modify/add_pending_folders.cpp @@ -177,6 +176,7 @@ add_library(syncspirit_core src/model/diff/peer/cluster_update.cpp src/model/diff/peer/rx_tx.cpp src/model/diff/peer/update_folder.cpp + src/model/diff/peer/update_remote_views.cpp src/model/misc/augmentation.cpp src/model/misc/block_iterator.cpp src/model/misc/error_code.cpp @@ -202,7 +202,7 @@ add_library(syncspirit_core src/model/ignored_folder.cpp src/model/pending_device.cpp src/model/pending_folder.cpp - src/model/remote_folder_info.cpp + src/model/remote_view.cpp src/model/some_device.cpp src/model/version.cpp src/net/acceptor_actor.cpp diff --git a/src/model/device.h b/src/model/device.h index 150a191e..8715b3c3 100644 --- a/src/model/device.h +++ b/src/model/device.h @@ -7,7 +7,7 @@ #include "misc/map.hpp" #include "device_id.h" #include "device_state.h" -#include "remote_folder_info.h" +#include "remote_view.h" #include "utils/uri.h" #include "utils/bytes.h" #include "syncspirit-export.h" @@ -58,7 +58,7 @@ struct SYNCSPIRIT_API device_t : augmentable_t { inline bool has_auto_accept() const noexcept { return auto_accept; } inline bool is_paused() const noexcept { return paused; } inline bool get_skip_introduction_removals() const noexcept { return skip_introduction_removals; } - inline auto &get_remote_folder_infos() noexcept { return remote_folder_infos; } + inline auto &get_remote_view_map() noexcept { return remote_view_map; } inline const pt::ptime &get_last_seen() const noexcept { return last_seen; } inline const uris_t &get_uris() const noexcept { return uris; } @@ -98,7 +98,7 @@ struct SYNCSPIRIT_API device_t : augmentable_t { file_iterator_ptr_t iterator; - remote_folder_infos_map_t remote_folder_infos; + remote_view_map_t remote_view_map; pt::ptime last_seen; std::size_t rx_bytes; std::size_t tx_bytes; diff --git a/src/model/diff/cluster_visitor.cpp b/src/model/diff/cluster_visitor.cpp index e724bf91..a7f0cf34 100644 --- a/src/model/diff/cluster_visitor.cpp +++ b/src/model/diff/cluster_visitor.cpp @@ -31,7 +31,6 @@ #include "modify/add_ignored_device.h" #include "modify/add_pending_device.h" #include "modify/add_pending_folders.h" -#include "modify/add_remote_folder_infos.h" #include "modify/block_ack.h" #include "modify/mark_reachable.h" #include "modify/remove_blocks.h" @@ -52,6 +51,7 @@ #include "peer/cluster_update.h" #include "peer/rx_tx.h" #include "peer/update_folder.h" +#include "peer/update_remote_views.h" using namespace syncspirit::model::diff; @@ -179,6 +179,11 @@ auto cluster_visitor_t::operator()(const peer::update_folder_t &diff, void *cust return diff.visit_next(*this, custom); } +auto cluster_visitor_t::operator()(const peer::update_remote_views_t &diff, void *custom) noexcept + -> outcome::result { + return diff.visit_next(*this, custom); +} + auto cluster_visitor_t::operator()(const local::blocks_availability_t &diff, void *custom) noexcept -> outcome::result { return diff.visit_next(*this, custom); @@ -197,11 +202,6 @@ auto cluster_visitor_t::operator()(const modify::add_blocks_t &diff, void *custo return diff.visit_next(*this, custom); } -auto cluster_visitor_t::operator()(const modify::add_remote_folder_infos_t &diff, void *custom) noexcept - -> outcome::result { - return diff.visit_next(*this, custom); -} - auto cluster_visitor_t::operator()(const modify::add_ignored_device_t &diff, void *custom) noexcept -> outcome::result { return diff.visit_next(*this, custom); diff --git a/src/model/diff/cluster_visitor.h b/src/model/diff/cluster_visitor.h index c771514f..6dfb5ac7 100644 --- a/src/model/diff/cluster_visitor.h +++ b/src/model/diff/cluster_visitor.h @@ -44,12 +44,12 @@ struct SYNCSPIRIT_API cluster_visitor_t { virtual outcome::result operator()(const peer::cluster_update_t &, void *custom) noexcept; virtual outcome::result operator()(const peer::rx_tx_t &, void *custom) noexcept; virtual outcome::result operator()(const peer::update_folder_t &, void *custom) noexcept; + virtual outcome::result operator()(const peer::update_remote_views_t &, void *custom) noexcept; virtual outcome::result operator()(const modify::add_blocks_t &, void *custom) noexcept; virtual outcome::result operator()(const modify::add_ignored_device_t &, void *custom) noexcept; virtual outcome::result operator()(const modify::add_pending_device_t &, void *custom) noexcept; virtual outcome::result operator()(const modify::add_pending_folders_t &, void *custom) noexcept; - virtual outcome::result operator()(const modify::add_remote_folder_infos_t &, void *custom) noexcept; virtual outcome::result operator()(const modify::block_ack_t &, void *custom) noexcept; virtual outcome::result operator()(const modify::mark_reachable_t &, void *custom) noexcept; virtual outcome::result operator()(const modify::remove_blocks_t &, void *custom) noexcept; diff --git a/src/model/diff/diffs_fwd.h b/src/model/diff/diffs_fwd.h index 5a4dca70..05141f11 100644 --- a/src/model/diff/diffs_fwd.h +++ b/src/model/diff/diffs_fwd.h @@ -51,6 +51,7 @@ namespace peer { struct cluster_update_t; struct rx_tx_t; struct update_folder_t; +struct update_remote_views_t; } // namespace peer namespace modify { @@ -58,7 +59,6 @@ struct add_blocks_t; struct add_ignored_device_t; struct add_pending_device_t; struct add_pending_folders_t; -struct add_remote_folder_infos_t; struct block_ack_t; struct block_transaction_t; struct generic_remove_t; diff --git a/src/model/diff/modify/add_remote_folder_infos.cpp b/src/model/diff/modify/add_remote_folder_infos.cpp deleted file mode 100644 index a2382696..00000000 --- a/src/model/diff/modify/add_remote_folder_infos.cpp +++ /dev/null @@ -1,50 +0,0 @@ -// SPDX-License-Identifier: GPL-3.0-or-later -// SPDX-FileCopyrightText: 2024-2025 Ivan Baidakou - -#include "add_remote_folder_infos.h" -#include "model/cluster.h" -#include "model/diff/apply_controller.h" -#include "model/diff/cluster_visitor.h" -#include "model/misc/error_code.h" - -using namespace syncspirit::model::diff::modify; - -add_remote_folder_infos_t::add_remote_folder_infos_t(const model::device_t &peer, container_t items) noexcept - : container{std::move(items)} { - auto &peer_device = peer.device_id(); - device_id = peer_device.get_sha256(); - for (auto &item : container) { - LOG_DEBUG(log, "add_remote_folder_infos_t, device = {}, folder = {}, index = {:#x}, max seq. = {}", - peer_device.get_short(), item.folder_id, item.index_id, item.max_sequence); - } -} - -auto add_remote_folder_infos_t::apply_impl(apply_controller_t &controller, void *custom) const noexcept - -> outcome::result { - auto &cluster = controller.get_cluster(); - auto &devices = cluster.get_devices(); - auto &folders = cluster.get_folders(); - auto peer = devices.by_sha256(device_id); - if (!peer) { - return make_error_code(error_code_t::no_such_device); - } - auto &remote_folders = peer->get_remote_folder_infos(); - for (auto &item : container) { - auto folder = folders.by_id(item.folder_id); - if (!folder) { - return make_error_code(error_code_t::no_such_folder); - } - auto opt = model::remote_folder_info_t::create(item.index_id, item.max_sequence, *peer, *folder); - if (!opt) { - return opt.assume_error(); - } - remote_folders.put(opt.assume_value()); - } - return applicator_t::apply_sibling(controller, custom); -} - -auto add_remote_folder_infos_t::visit(cluster_visitor_t &visitor, void *custom) const noexcept - -> outcome::result { - LOG_TRACE(log, "visiting add_remote_folder_infos_t"); - return visitor(*this, custom); -} diff --git a/src/model/diff/modify/share_folder.cpp b/src/model/diff/modify/share_folder.cpp index dfe28bdc..db4a14d9 100644 --- a/src/model/diff/modify/share_folder.cpp +++ b/src/model/diff/modify/share_folder.cpp @@ -5,7 +5,6 @@ #include "model/cluster.h" #include "model/misc/error_code.h" #include "model/diff/cluster_visitor.h" -#include "add_remote_folder_infos.h" #include "remove_pending_folders.h" #include "upsert_folder_info.h" #include "utils/format.hpp" @@ -42,17 +41,12 @@ share_folder_t::share_folder_t(const bu::uuid &uuid, const model::device_t &peer LOG_DEBUG(log, "share_folder_t, with peer = {}, folder_id = {}", peer.device_id(), folder_id); auto current = assign_child(new upsert_folder_info_t(uuid, peer.device_id(), introducer, folder_id, index_id)); if (pf) { - using container_t = typename add_remote_folder_infos_t::container_t; - using item_t = typename container_t::value_type; auto keys = remove_pending_folders_t::keys_t{}; auto key = pf->get_key(); auto bytes = utils::bytes_t(key.begin(), key.end()); keys.emplace_back(std::move(bytes)); auto diff = cluster_diff_ptr_t{}; current = current->assign_sibling(new remove_pending_folders_t(std::move(keys))); - - auto remote_folders = container_t{{item_t{folder_id, index_id, 0}}}; - current = current->assign_sibling(new add_remote_folder_infos_t(peer, std::move(remote_folders))); } } diff --git a/src/model/diff/modify/upsert_folder.h b/src/model/diff/modify/upsert_folder.h index 4bbb5b69..9f021c55 100644 --- a/src/model/diff/modify/upsert_folder.h +++ b/src/model/diff/modify/upsert_folder.h @@ -5,6 +5,7 @@ #include "../cluster_diff.h" #include "model/device.h" +#include "model/folder_info.h" #include "model/misc/sequencer.h" #include "proto/proto-fwd.hpp" diff --git a/src/model/diff/peer/cluster_update.cpp b/src/model/diff/peer/cluster_update.cpp index 2063a79b..e25f895e 100644 --- a/src/model/diff/peer/cluster_update.cpp +++ b/src/model/diff/peer/cluster_update.cpp @@ -3,7 +3,6 @@ #include "cluster_update.h" #include "model/diff/apply_controller.h" -#include "model/diff/modify/add_remote_folder_infos.h" #include "model/diff/modify/add_pending_folders.h" #include "model/diff/modify/remove_blocks.h" #include "model/diff/modify/remove_folder_infos.h" @@ -13,6 +12,7 @@ #include "model/diff/modify/update_peer.h" #include "model/diff/modify/upsert_folder.h" #include "model/diff/modify/upsert_folder_info.h" +#include "model/diff/peer/update_remote_views.h" #include "model/diff/cluster_visitor.h" #include "model/cluster.h" #include "model/misc/orphaned_blocks.h" @@ -50,6 +50,7 @@ cluster_update_t::cluster_update_t(const bfs::path &default_path, const cluster_ using allocator_t = std::pmr::polymorphic_allocator; using fmt_buff_t = fmt::basic_memory_buffer; using fi_set_t = std::pmr::unordered_set; + using view_t = peer::update_remote_views_t::item_t; struct introduced_device_t { db::Device device; model::device_id_t device_id; @@ -74,7 +75,7 @@ cluster_update_t::cluster_update_t(const bfs::path &default_path, const cluster_ auto &known_pending_folders = cluster.get_pending_folders(); auto new_pending_folders = diff::modify::add_pending_folders_t::container_t{}; - auto remote_folders = diff::modify::add_remote_folder_infos_t::container_t{}; + auto remote_views = diff::peer::update_remote_views_t::container_t{}; uuid_folder_infos_map_t reset_folders; uuid_folder_infos_map_t removed_folders; auto reshared_folders = fi_set_t(allocator); @@ -285,9 +286,15 @@ cluster_update_t::cluster_update_t(const bfs::path &default_path, const cluster_ folder_info = folder->get_folder_infos().by_device_id(device_sha); } + if (device_sha != sha256 && device.get() != cluster.get_device()) { + continue; + } + + auto view = view_t{std::string(folder_id), utils::bytes_t(device_sha), index_id, max_sequence}; + remote_views.emplace_back(std::move(view)); + if (device.get() == cluster.get_device()) { if (is_shared_with_source(folder_id)) { - remote_folders.emplace_back(std::string(folder_id), index_id, max_sequence); LOG_DEBUG(log, "cluster_update_t, remote folder = {}, device = {}, max seq. = {}", folder_label, device_id.get_short(), max_sequence); } else { @@ -297,10 +304,6 @@ cluster_update_t::cluster_update_t(const bfs::path &default_path, const cluster_ continue; } - if (device_sha != sha256) { - continue; - } - if (!folder_info) { bool share = false; if (device_sha == source.device_id().get_sha256()) { @@ -489,8 +492,8 @@ cluster_update_t::cluster_update_t(const bfs::path &default_path, const cluster_ auto ptr = new modify::add_pending_folders_t(std::move(new_pending_folders)); update_current(ptr); } - if (!remote_folders.empty()) { - auto ptr = new modify::add_remote_folder_infos_t(source, std::move(remote_folders)); + if (!remote_views.empty()) { + auto ptr = new peer::update_remote_views_t(source, std::move(remote_views)); update_current(ptr); } for (auto &id : introduced_devices) { @@ -509,7 +512,7 @@ auto cluster_update_t::apply_impl(apply_controller_t &controller, void *custom) LOG_TRACE(log, "applying cluster_update_t (self)"); auto &cluster = controller.get_cluster(); auto peer = cluster.get_devices().by_sha256(peer_id); - peer->get_remote_folder_infos().clear(); + peer->get_remote_view_map().clear(); LOG_TRACE(log, "applying cluster_update_t (children)"); auto r = applicator_t::apply_child(controller, custom); diff --git a/src/model/diff/peer/update_remote_views.cpp b/src/model/diff/peer/update_remote_views.cpp new file mode 100644 index 00000000..30f8198b --- /dev/null +++ b/src/model/diff/peer/update_remote_views.cpp @@ -0,0 +1,41 @@ +// SPDX-License-Identifier: GPL-3.0-or-later +// SPDX-FileCopyrightText: 2025 Ivan Baidakou + +#include "update_remote_views.h" +#include "model/cluster.h" +#include "model/diff/apply_controller.h" +#include "model/diff/cluster_visitor.h" + +using namespace syncspirit; +using namespace syncspirit::model::diff::peer; + +update_remote_views_t::update_remote_views_t(const model::device_t &peer_, container_t container_) noexcept + : container{std::move(container_)}, peer_id{peer_.device_id().get_sha256()} { + LOG_DEBUG(log, "update_remote_views_t '{}', {} views", peer_.device_id().get_short(), container.size()); +} + +auto update_remote_views_t::apply_impl(apply_controller_t &controller, void *custom) const noexcept + -> outcome::result { + LOG_TRACE(log, "applying update_remote_views_t"); + + auto &cluster = controller.get_cluster(); + auto peer = cluster.get_devices().by_sha256(peer_id); + auto &views = peer->get_remote_view_map(); + auto &folders = cluster.get_folders(); + auto &devices = cluster.get_devices(); + for (auto &item : container) { + auto folder = folders.by_id(item.folder_id); + auto device = devices.by_sha256(item.device_id); + if (folder && device) { + views.push(*device, *folder, item.index_id, item.max_sequence); + LOG_TRACE(log, "'{}' update remote view of folder '{}' to max seq. {}", device->device_id().get_short(), + folder->get_id(), item.max_sequence); + } + } + return applicator_t::apply_sibling(controller, custom); +} + +auto update_remote_views_t::visit(cluster_visitor_t &visitor, void *custom) const noexcept -> outcome::result { + LOG_TRACE(log, "visiting update_remote_views_t"); + return visitor(*this, custom); +} diff --git a/src/model/diff/modify/add_remote_folder_infos.h b/src/model/diff/peer/update_remote_views.h similarity index 58% rename from src/model/diff/modify/add_remote_folder_infos.h rename to src/model/diff/peer/update_remote_views.h index 137207cf..c951449a 100644 --- a/src/model/diff/modify/add_remote_folder_infos.h +++ b/src/model/diff/peer/update_remote_views.h @@ -1,28 +1,30 @@ // SPDX-License-Identifier: GPL-3.0-or-later -// SPDX-FileCopyrightText: 2024-2025 Ivan Baidakou +// SPDX-FileCopyrightText: 2025 Ivan Baidakou #pragma once #include "../cluster_diff.h" -#include "model/device.h" #include +#include "model/device.h" -namespace syncspirit::model::diff::modify { +namespace syncspirit::model::diff::peer { -struct SYNCSPIRIT_API add_remote_folder_infos_t final : cluster_diff_t { +struct SYNCSPIRIT_API update_remote_views_t final : cluster_diff_t { struct item_t { std::string folder_id; + utils::bytes_t device_id; std::uint64_t index_id; std::int64_t max_sequence; }; using container_t = std::vector; - add_remote_folder_infos_t(const model::device_t &peer, container_t items) noexcept; + update_remote_views_t(const model::device_t &peer, container_t container) noexcept; outcome::result apply_impl(apply_controller_t &, void *) const noexcept override; outcome::result visit(cluster_visitor_t &, void *) const noexcept override; - utils::bytes_t device_id; + private: container_t container; + utils::bytes_t peer_id; }; -} // namespace syncspirit::model::diff::modify +} // namespace syncspirit::model::diff::peer diff --git a/src/model/misc/updates_streamer.cpp b/src/model/misc/updates_streamer.cpp index cc36561b..5afa592a 100644 --- a/src/model/misc/updates_streamer.cpp +++ b/src/model/misc/updates_streamer.cpp @@ -2,7 +2,6 @@ // SPDX-FileCopyrightText: 2023-2025 Ivan Baidakou #include "updates_streamer.h" -#include "model/remote_folder_info.h" #include #include @@ -15,7 +14,7 @@ updates_streamer_t::updates_streamer_t(cluster_t &cluster_, device_t &device) no void updates_streamer_t::refresh_remote() noexcept { auto &folders = cluster.get_folders(); - auto &remote_folders = peer->get_remote_folder_infos(); + auto &remote_views = peer->get_remote_view_map(); auto streaming_folder = (model::folder_info_t *)(nullptr); auto prev_seen = std::move(seen_info); seen_info = {}; @@ -28,10 +27,10 @@ void updates_streamer_t::refresh_remote() noexcept { if (streaming && streaming->folder_info == local_folder) { streaming_folder = local_folder.get(); } - auto remote_folder = remote_folders.by_folder(folder); - if (remote_folder) { - auto index_match = remote_folder->get_index() == local_folder->get_index(); - auto remote_max = index_match ? remote_folder->get_max_sequence() : 0; + auto remote_view = remote_views.get(*cluster.get_device(), folder); + if (remote_view) { + auto index_match = remote_view->index_id == local_folder->get_index(); + auto remote_max = index_match ? remote_view->max_sequence : 0; auto previously_seen = prev_seen[local_folder]; auto seen = std::max(remote_max, previously_seen); seen_info[local_folder] = seen; @@ -42,9 +41,12 @@ void updates_streamer_t::refresh_remote() noexcept { if (streaming && !streaming_folder) { streaming.reset(); } else if (streaming_folder) { - auto remote_folder = remote_folders.by_folder(*streaming_folder->get_folder()); - if (!remote_folder) { - streaming.reset(); + auto &folder = *streaming_folder->get_folder(); + auto remote_view = remote_views.get(*cluster.get_device(), folder); + if (remote_view) { + if (remote_view->index_id != streaming_folder->get_index()) { + streaming.reset(); + } } else { // TODO, refresh files? } diff --git a/src/model/misc/updates_streamer.h b/src/model/misc/updates_streamer.h index 3dec0a40..2f2ec5c9 100644 --- a/src/model/misc/updates_streamer.h +++ b/src/model/misc/updates_streamer.h @@ -1,5 +1,5 @@ // SPDX-License-Identifier: GPL-3.0-or-later -// SPDX-FileCopyrightText: 2023-2024 Ivan Baidakou +// SPDX-FileCopyrightText: 2023-2025 Ivan Baidakou #pragma once @@ -7,7 +7,6 @@ #include "model/file_info.h" #include "model/device.h" #include "model/folder_info.h" -#include "model/remote_folder_info.h" #include "syncspirit-export.h" #include #include diff --git a/src/model/remote_folder_info.cpp b/src/model/remote_folder_info.cpp deleted file mode 100644 index 2fa14daa..00000000 --- a/src/model/remote_folder_info.cpp +++ /dev/null @@ -1,39 +0,0 @@ -#include "remote_folder_info.h" -#include "folder.h" -#include "cluster.h" - -namespace syncspirit::model { - -auto remote_folder_info_t::create(std::uint64_t index_id, std::int64_t max_sequence, device_t &device_, - folder_t &folder_) noexcept -> outcome::result { - auto ptr = remote_folder_info_t_ptr_t{new remote_folder_info_t(index_id, max_sequence, device_, folder_)}; - return outcome::success(ptr); -} - -remote_folder_info_t::~remote_folder_info_t() {} - -remote_folder_info_t::remote_folder_info_t(std::uint64_t index_id_, std::int64_t max_sequence_, device_t &device_, - folder_t &folder_) noexcept - : index_id{index_id_}, max_sequence{max_sequence_}, device{&device_}, folder{&folder_} {} - -std::string_view remote_folder_info_t::get_key() const noexcept { return folder->get_id(); } - -remote_folder_info_t_ptr_t remote_folder_infos_map_t::by_folder(const folder_t &folder) const noexcept { - auto id = folder.get_id(); - auto ptr = (unsigned char *)id.data(); - auto view = utils::bytes_view_t(ptr, id.size()); - return get<0>(view); -} - -auto remote_folder_info_t::get_local() const noexcept -> folder_info_ptr_t { - auto device = folder->get_cluster()->get_device(); - return folder->get_folder_infos().by_device(*device); -} - -template <> SYNCSPIRIT_API utils::bytes_view_t get_index<0>(const remote_folder_info_t_ptr_t &item) noexcept { - auto key = item->get_key(); - auto ptr = (unsigned char *)key.data(); - return {ptr, key.size()}; -} - -} // namespace syncspirit::model diff --git a/src/model/remote_folder_info.h b/src/model/remote_folder_info.h deleted file mode 100644 index 42198221..00000000 --- a/src/model/remote_folder_info.h +++ /dev/null @@ -1,55 +0,0 @@ -// SPDX-License-Identifier: GPL-3.0-or-later -// SPDX-FileCopyrightText: 2023-2025 Ivan Baidakou - -#pragma once - -#include -#include "syncspirit-export.h" -#include "misc/augmentation.h" -#include "misc/map.hpp" -#include - -namespace syncspirit::model { - -namespace outcome = boost::outcome_v2; - -struct folder_t; -using folder_ptr_t = intrusive_ptr_t; - -struct device_t; -using device_ptr_t = intrusive_ptr_t; - -struct remote_folder_info_t; -using remote_folder_info_t_ptr_t = intrusive_ptr_t; - -struct folder_info_t; -using folder_info_ptr_t = intrusive_ptr_t; - -struct SYNCSPIRIT_API remote_folder_info_t final : augmentable_t { - - static outcome::result create(std::uint64_t index_id, std::int64_t max_sequence, - device_t &device_, folder_t &folder_) noexcept; - - ~remote_folder_info_t(); - std::string_view get_key() const noexcept; - - inline std::uint64_t get_index() const noexcept { return index_id; } - inline std::int64_t get_max_sequence() const noexcept { return max_sequence; } - - folder_info_ptr_t get_local() const noexcept; - - private: - remote_folder_info_t(std::uint64_t index_id, std::int64_t max_sequence, device_t &device_, - folder_t &folder_) noexcept; - - std::uint64_t index_id; - std::int64_t max_sequence; - device_t *device; - folder_ptr_t folder; -}; - -struct SYNCSPIRIT_API remote_folder_infos_map_t : public generic_map_t { - remote_folder_info_t_ptr_t by_folder(const folder_t &folder) const noexcept; -}; - -} // namespace syncspirit::model diff --git a/src/model/remote_view.cpp b/src/model/remote_view.cpp new file mode 100644 index 00000000..8e159b83 --- /dev/null +++ b/src/model/remote_view.cpp @@ -0,0 +1,37 @@ +// SPDX-License-Identifier: GPL-3.0-or-later +// SPDX-FileCopyrightText: 2025 Ivan Baidakou + +#include "remote_view.h" +#include "device.h" +#include "folder.h" + +using namespace syncspirit; +using namespace syncspirit::model; +using namespace syncspirit::model::details; + +template inline static std::size_t get_hash(const T &key) noexcept { + auto h1 = std::hash{}(key.folder_id); + auto h2 = std::hash{}(key.device_id); + return h1 + 0x9e3779b9 + (h2 << 6) + (h2 >> 2); +} + +std::size_t remote_view_key_hash_t::operator()(const remote_view_key_t &key) const noexcept { return get_hash(key); } + +std::size_t remote_view_key_hash_t::operator()(const transient_view_key_t &key) const noexcept { return get_hash(key); } + +void remote_view_map_t::push(const device_t &device, const folder_t &folder, std::uint64_t index_id, + std::int64_t max_sequence) noexcept { + auto folder_id = std::string(folder.get_id()); + auto device_id = utils::bytes_t(device.device_id().get_sha256()); + auto key = details::remote_view_key_t(std::move(folder_id), std::move(device_id)); + emplace(std::move(key), remote_view_t{index_id, max_sequence}); +} + +const remote_view_t *remote_view_map_t::get(const device_t &device, const folder_t &folder) const noexcept { + auto key = details::transient_view_key_t{folder.get_id(), device.device_id().get_sha256()}; + auto it = find(key); + if (it != end()) { + return &it->second; + } + return {}; +} diff --git a/src/model/remote_view.h b/src/model/remote_view.h new file mode 100644 index 00000000..d6fb8ffb --- /dev/null +++ b/src/model/remote_view.h @@ -0,0 +1,57 @@ +// SPDX-License-Identifier: GPL-3.0-or-later +// SPDX-FileCopyrightText: 2025 Ivan Baidakou + +#pragma once + +#include +#include +#include +#include "utils/bytes.h" +#include "syncspirit-export.h" + +namespace syncspirit::model { + +struct device_t; +struct folder_t; + +struct remote_view_t { + std::uint64_t index_id; + std::int64_t max_sequence; +}; + +namespace details { + +struct remote_view_key_t { + std::string folder_id; + utils::bytes_t device_id; +}; + +struct transient_view_key_t { + std::string_view folder_id; + utils::bytes_view_t device_id; +}; + +struct SYNCSPIRIT_API remote_view_key_eq_t { + using is_transparent = void; + template bool operator()(const U &lhs, const V &rhs) const { + return lhs.folder_id == rhs.folder_id && lhs.device_id == rhs.device_id; + } +}; + +struct SYNCSPIRIT_API remote_view_key_hash_t { + using is_transparent = void; + std::size_t operator()(const remote_view_key_t &key) const noexcept; + std::size_t operator()(const transient_view_key_t &key) const noexcept; +}; + +using remote_view_map_base_t = + std::unordered_map; + +} // namespace details + +struct SYNCSPIRIT_API remote_view_map_t : details::remote_view_map_base_t { + void push(const device_t &, const folder_t &, std::uint64_t index_id, std::int64_t max_sequence) noexcept; + const remote_view_t *get(const device_t &, const folder_t &) const noexcept; +}; + +} // namespace syncspirit::model diff --git a/src/net/controller_actor.cpp b/src/net/controller_actor.cpp index 9d4de327..68df9c92 100644 --- a/src/net/controller_actor.cpp +++ b/src/net/controller_actor.cpp @@ -323,17 +323,17 @@ void controller_actor_t::send_cluster_config(stack_context_t &ctx) noexcept { void controller_actor_t::send_new_indices() noexcept { if (updates_streamer && peer_address) { - auto &remote_folders = peer->get_remote_folder_infos(); + auto &remote_views = peer->get_remote_view_map(); for (auto it : cluster->get_folders()) { auto &folder = *it.item; auto peer_folder = folder.is_shared_with(*peer); if (peer_folder) { auto local_folder = folder.get_folder_infos().by_device(*cluster->get_device()); - auto remote_folder = remote_folders.by_folder(folder); - if (remote_folder) { - if (remote_folder->get_index() != local_folder->get_index()) { + auto remote_view = remote_views.get(*cluster->get_device(), folder); + if (remote_view) { + if (remote_view->index_id != local_folder->get_index()) { LOG_DEBUG(log, "peer still has wrong index for '{}' ({:#x} vs {:#x}), refreshing", - folder.get_id(), remote_folder->get_index(), local_folder->get_index()); + folder.get_id(), remote_view->index_id, local_folder->get_index()); updates_streamer->on_remote_refresh(); } } diff --git a/src/net/local_keeper/child_info.h b/src/net/local_keeper/child_info.h index f7f24829..5fdb728c 100644 --- a/src/net/local_keeper/child_info.h +++ b/src/net/local_keeper/child_info.h @@ -4,6 +4,7 @@ #pragma once #include "presentation/presence.h" +#include "model/folder_info.h" #include "fs/task/scan_dir.h" #include #include diff --git a/src/presentation/folder_entity.h b/src/presentation/folder_entity.h index 8eaa4993..9f24dbb6 100644 --- a/src/presentation/folder_entity.h +++ b/src/presentation/folder_entity.h @@ -6,6 +6,7 @@ #include "entity.h" #include "orphans.h" #include "model/file_info.h" +#include "model/folder.h" namespace syncspirit::presentation { diff --git a/src/presentation/folder_presence.h b/src/presentation/folder_presence.h index 627270e6..a56ffaf0 100644 --- a/src/presentation/folder_presence.h +++ b/src/presentation/folder_presence.h @@ -4,6 +4,7 @@ #pragma once #include "presence.h" +#include "model/folder_info.h" #include "syncspirit-export.h" namespace syncspirit::presentation { diff --git a/tests/031-diff-cluster_update.cpp b/tests/031-diff-cluster_update.cpp index dabd1138..6eb79bd8 100644 --- a/tests/031-diff-cluster_update.cpp +++ b/tests/031-diff-cluster_update.cpp @@ -730,14 +730,14 @@ TEST_CASE("cluster update with remote folders (1)", "[model]") { auto &pr_peer = proto::add_devices(pr_folder); proto::set_id(pr_peer, peer_id_1.get_sha256()); proto::set_name(pr_peer, peer_device->get_name()); - proto::set_max_sequence(pr_peer, 123456u); - proto::set_index_id(pr_peer, 7u); + proto::set_index_id(pr_peer, 123456u); + proto::set_max_sequence(pr_peer, 7u); auto &pr_peer_my = proto::add_devices(pr_folder); proto::set_id(pr_peer_my, my_id.get_sha256()); proto::set_name(pr_peer_my, my_device->get_name()); - proto::set_max_sequence(pr_peer_my, 3); proto::set_index_id(pr_peer_my, 5ul); + proto::set_max_sequence(pr_peer_my, 3); auto diff_opt = diff::peer::cluster_update_t::create({}, *cluster, *sequencer, *peer_device, *cc); REQUIRE(diff_opt); @@ -745,10 +745,17 @@ TEST_CASE("cluster update with remote folders (1)", "[model]") { auto opt = diff_opt.value()->apply(*controller, {}); REQUIRE(opt); - auto remote_folder = peer_device->get_remote_folder_infos().by_folder(*folder); - REQUIRE(remote_folder); - CHECK(remote_folder->get_index() == 5ul); - CHECK(remote_folder->get_max_sequence() == 3); + auto remote_views = peer_device->get_remote_view_map(); + REQUIRE(remote_views.size() == 2); + auto view_peer = remote_views.get(*peer_device, *folder); + REQUIRE(view_peer); + CHECK(view_peer->index_id == 123456u); + CHECK(view_peer->max_sequence == 7); + + auto view_local = remote_views.get(*my_device, *folder); + REQUIRE(view_local); + CHECK(view_local->index_id == 5u); + CHECK(view_local->max_sequence == 3); SECTION("unshare by peer") { auto cc = std::make_unique(); @@ -758,7 +765,7 @@ TEST_CASE("cluster update with remote folders (1)", "[model]") { auto &diff = diff_opt.value(); REQUIRE(diff->apply(*controller, {})); - CHECK(peer_device->get_remote_folder_infos().size() == 0); + CHECK(peer_device->get_remote_view_map().size() == 0); auto fi = folder->get_folder_infos().by_device(*peer_device); // we are still sharing the folder with peer CHECK(fi); diff --git a/tests/054-updates_streamer.cpp b/tests/054-updates_streamer.cpp index 33935e5e..499268e5 100644 --- a/tests/054-updates_streamer.cpp +++ b/tests/054-updates_streamer.cpp @@ -33,8 +33,8 @@ TEST_CASE("updates_streamer", "[model]") { auto folder = folders.by_id("1234-5678"); auto add_remote = [&](std::uint64_t index, std::int64_t sequence) { - auto remote_folder = remote_folder_info_t::create(index, sequence, *peer_device, *folder).value(); - peer_device->get_remote_folder_infos().put(remote_folder); + auto &views = peer_device->get_remote_view_map(); + views.push(*my_device, *folder, index, sequence); }; SECTION("trivial") {