3 Commits f3e794d8fd ... dc95b5f525

Autor SHA1 Mensaje Fecha
  Ivan Baidakou dc95b5f525 core: use compact vector hace 6 días
  Ivan Baidakou 58a3b10537 WIP hace 6 días
  Ivan Baidakou 0116ac796e WIP hace 6 días

+ 1 - 1
src/fs/scan_task.cpp

@@ -359,7 +359,7 @@ scan_result_t scan_task_t::do_advance(unknown_file_t file) noexcept {
                     peer_file = std::move(f);
                     peer_counter = peer_file->get_version().get_best();
                 } else {
-                    auto &c = f->get_version().get_best();
+                    auto c = f->get_version().get_best();
                     if (proto::get_value(peer_counter) < proto::get_value(c)) {
                         peer_counter = c;
                         peer_file = std::move(f);

+ 2 - 0
src/model/block_info.h

@@ -95,6 +95,8 @@ struct SYNCSPIRIT_API block_info_t {
     template <typename T> void assign(const T &item) noexcept;
     block_info_t(utils::bytes_view_t key) noexcept;
     block_info_t(const proto::BlockInfo &block) noexcept;
+    block_info_t(block_info_t &&) noexcept = delete;
+    block_info_t(const block_info_t &) noexcept = delete;
 
     union file_blocks_union_t {
         file_blocks_union_t();

+ 3 - 3
src/model/file_info.cpp

@@ -301,7 +301,7 @@ db::FileInfo file_info_t::as_db(bool include_blocks) const noexcept {
             }
         }
     } else {
-        auto& container = content.non_file.symlink_target;
+        auto &container = content.non_file.symlink_target;
         auto ptr = container.data();
         auto link = std::string_view(ptr, ptr + container.size());
         db::set_symlink_target(r, link);
@@ -339,7 +339,7 @@ proto::FileInfo file_info_t::as_proto(bool include_blocks) const noexcept {
             }
         }
     } else {
-        auto& container = content.non_file.symlink_target;
+        auto &container = content.non_file.symlink_target;
         auto ptr = container.data();
         auto link = std::string_view(ptr, ptr + container.size());
         proto::set_symlink_target(r, link);
@@ -590,7 +590,7 @@ std::string file_info_t::make_conflicting_name() const noexcept {
     auto local = adjustor_t::utc_to_local(utc);
     auto ymd = local.date().year_month_day();
     auto time = local.time_of_day();
-    auto &counter = version.get_best();
+    auto counter = version.get_best();
     auto device_short = device_id_t::make_short(proto::get_id(counter));
     auto conflicted_name =
         fmt::format("{}.sync-conflict-{:04}{:02}{:02}-{:02}{:02}{:02}-{}{}", stem, (int)ymd.year, ymd.month.as_number(),

+ 5 - 5
src/model/file_info.h

@@ -9,7 +9,7 @@
 #include <filesystem>
 #include <boost/outcome.hpp>
 #include <boost/multi_index/ordered_index.hpp>
-#include "utils/vector.hpp"
+#include "utils/compact_vector.hpp"
 #include "misc/augmentation.h"
 #include "misc/path.h"
 #include "misc/map.hpp"
@@ -55,7 +55,7 @@ struct SYNCSPIRIT_API file_info_t {
     static constexpr std::uintptr_t LOCAL_MASK = 1 << 0;
     static constexpr std::uintptr_t PTR_MASK = ~LOCAL_MASK;
 
-    using blocks_t = utils::vector_t<block_info_t *>;
+    using blocks_t = utils::compact_vector_t<block_info_t *>;
 
     struct decomposed_key_t {
         utils::bytes_view_t folder_info_id;
@@ -167,7 +167,7 @@ struct SYNCSPIRIT_API file_info_t {
 
     std::string_view get_link_target() const noexcept {
         assert(flags & f_type_link);
-        auto& container = content.non_file.symlink_target;
+        auto &container = content.non_file.symlink_target;
         return {container.data(), container.size()};
     }
 
@@ -212,7 +212,7 @@ struct SYNCSPIRIT_API file_info_t {
     template <typename T> auto &access() const noexcept;
 
   private:
-    using string_t = utils::vector_t<char>;
+    using string_t = utils::compact_vector_t<char>;
     struct size_full_t {
         ~size_full_t();
         blocks_t blocks;
@@ -246,8 +246,8 @@ struct SYNCSPIRIT_API file_info_t {
     std::uint32_t permissions;
     std::uint32_t modified_ns;
 
-    version_t version;
     content_t content;
+    version_t version;
     std::uint16_t flags = 0;
     mutable std::uint16_t counter = 0;
 

+ 21 - 11
src/model/misc/path.cpp

@@ -13,18 +13,24 @@ using namespace boost::nowide;
 
 namespace syncspirit::model {
 
-path_t::path_t(std::string_view full_name) noexcept : name(full_name) {
+path_t::path_t(std::string_view full_name) noexcept {
+    name = string_t(full_name.data(), full_name.data() + full_name.size());
     auto file_path = bfs::path(widen(full_name));
     auto tmp = std::vector<char>(full_name.size() * 4);
     auto it = file_path.begin();
     auto root_name = it->wstring();
     auto ptr = narrow(tmp.data(), tmp.size(), root_name.data());
     auto prev = std::strlen(tmp.data());
-    for (++it; it != file_path.end(); ++it) {
+    ++it;
+    auto sz = std::distance(it, file_path.end());
+    pieces.resize(sz);
+    auto i = std::uint32_t{0};
+    for (; it != file_path.end(); ++it) {
         auto sub_name = it->wstring();
         auto ptr = narrow(tmp.data(), tmp.size(), sub_name.data());
-        pieces.emplace_back(prev + 1);
+        pieces[i] = static_cast<uint32_t>(prev + 1);
         prev += std::strlen(tmp.data()) + 1;
+        ++i;
     }
 }
 
@@ -35,12 +41,12 @@ path_t::path_t(path_t &source) noexcept {
 
 std::size_t path_t::get_pieces_size() const noexcept { return pieces.size() + (!name.empty() ? 1 : 0); }
 
-std::string_view path_t::get_full_name() const noexcept { return name; }
+std::string_view path_t::get_full_name() const noexcept { return std::string_view(name.data(), name.size()); }
 
 std::string_view path_t::get_parent_name() const noexcept {
     if (pieces.size()) {
         auto last_offset = pieces.back();
-        auto view = std::string_view(name);
+        auto view = std::string_view(name.data(), name.size());
         return view.substr(0, last_offset - 1);
     }
     return {};
@@ -49,10 +55,10 @@ std::string_view path_t::get_parent_name() const noexcept {
 std::string_view path_t::get_own_name() const noexcept {
     if (pieces.size()) {
         auto last_offset = pieces.back();
-        auto view = std::string_view(name);
-        return view.substr(last_offset);
+        auto view = std::string_view(name.data() + last_offset, name.size() - last_offset);
+        return view;
     }
-    return name;
+    return std::string_view(name.data(), name.size());
 }
 
 auto path_t::begin() const noexcept -> iterator_t { return iterator_t(this); };
@@ -60,8 +66,11 @@ auto path_t::begin() const noexcept -> iterator_t { return iterator_t(this); };
 auto path_t::end() const noexcept -> iterator_t { return iterator_t(); }
 
 bool path_t::contains(const path_t &other) const noexcept {
-    auto view = std::string_view(other.name);
-    return view.find(name) == 0;
+    auto ptr = other.name.data();
+    auto end = ptr + other.name.sz;
+    auto view = std::string_view(ptr, end);
+    auto self = std::string_view(name.data(), name.size());
+    return view.find(self) == 0;
 }
 
 using I = path_t::iterator_t;
@@ -78,7 +87,8 @@ auto I::operator*() const noexcept -> reference {
     auto b = position ? path->pieces[position - 1] : 0;
     auto e = position < path->pieces.size() ? path->pieces[position] - 1 : std::string::npos;
     auto s = e - b;
-    auto view = std::string_view(path->name);
+    auto &n = path->name;
+    auto view = std::string_view(n.data(), n.data() + n.size());
     return view.substr(b, s);
 }
 

+ 5 - 4
src/model/misc/path.h

@@ -5,9 +5,9 @@
 
 #include "syncspirit-export.h"
 #include "arc.hpp"
-#include <string>
-#include <vector>
 #include <cstdint>
+#include <string_view>
+#include "utils/compact_vector.hpp"
 
 namespace syncspirit::model {
 
@@ -47,8 +47,9 @@ struct SYNCSPIRIT_API path_t : arc_base_t<path_t> {
     bool contains(const path_t &other) const noexcept;
 
   protected:
-    using pieces_t = std::vector<std::uint32_t>;
-    std::string name;
+    using string_t = utils::compact_vector_t<char>;
+    using pieces_t = utils::compact_vector_t<std::uint32_t>;
+    string_t name;
     pieces_t pieces;
 };
 

+ 1 - 1
src/model/misc/path_cache.cpp

@@ -13,7 +13,7 @@ struct cached_path_t : path_t {
     }
 
     ~cached_path_t() {
-        cache.map.erase(name);
+        cache.map.erase(get_full_name());
         intrusive_ptr_release(&cache);
     }
 

+ 2 - 2
src/model/misc/resolver.cpp

@@ -14,8 +14,8 @@ static advance_action_t compare_by_version(const file_info_t &remote, const file
     auto &r_v = remote.get_version();
     auto &l_v = local.get_version();
 
-    auto &r_best = r_v.get_best();
-    auto &l_best = l_v.get_best();
+    auto r_best = r_v.get_best();
+    auto l_best = l_v.get_best();
     auto rv = proto::get_value(r_best);
     auto lv = proto::get_value(l_best);
     auto r_id = proto::get_id(r_best);

+ 61 - 37
src/model/version.cpp

@@ -5,20 +5,19 @@
 #include "device.h"
 #include "proto/proto-helpers.h"
 #include "utils/time.h"
-#include <limits>
-
-static constexpr auto undef = std::numeric_limits<uint32_t>::max();
 
 using namespace syncspirit::model;
 
-version_t::version_t() noexcept : best_index{undef} {}
+static constexpr std::uint64_t BEST_MASK = 1ull << 63;
+
+version_t::version_t() noexcept {}
 
 version_t::version_t(const proto::Vector &v) noexcept {
     auto counters_sz = proto::get_counters_size(v);
     assert(counters_sz);
     counters.resize(counters_sz);
     auto best = proto::get_counters(v, 0);
-    best_index = 0;
+    auto best_index = 0;
     for (int i = 0; i < counters_sz; ++i) {
         auto &c = proto::get_counters(v, i);
         counters[i] = c;
@@ -27,13 +26,14 @@ version_t::version_t(const proto::Vector &v) noexcept {
             best_index = i;
         }
     }
-}
 
-version_t::version_t(const device_t &device) noexcept : best_index{undef} {
-    counters.reserve(1);
-    update(device);
+    auto &selected = counters[best_index];
+    auto marked = proto::get_value(selected) | BEST_MASK;
+    proto::set_value(selected, marked);
 }
 
+version_t::version_t(const device_t &device) noexcept { update(device); }
+
 auto version_t::as_proto() const noexcept -> proto::Vector {
     proto::Vector v;
     to_proto(v);
@@ -43,7 +43,9 @@ auto version_t::as_proto() const noexcept -> proto::Vector {
 void version_t::to_proto(proto::Vector &v) const noexcept {
     proto::clear_counters(v);
     for (auto &c : counters) {
-        proto::add_counters(v, c);
+        auto id = proto::get_id(c);
+        auto value = proto::get_value(c);
+        proto::add_counters(v, proto::Counter(id, value & ~BEST_MASK));
     }
 }
 
@@ -52,43 +54,54 @@ void version_t::update(const device_t &device) noexcept {
     auto id = device.device_id().get_uint();
     auto v = static_cast<std::uint64_t>(utils::as_seconds(clock_t::universal_time()));
     auto counter = (proto::Counter *)(nullptr);
-    if (best_index != undef) {
-        v = std::max(proto::get_value(counters[best_index]) + 1, v);
-        best_index = undef;
-        for (size_t i = 0; i < counters.size(); ++i) {
-            if (proto::get_id(counters[i]) == id) {
-                counter = &counters[i];
-                best_index = i;
-                break;
+    int best_index = -1;
+    for (auto &c : counters) {
+        auto value = proto::get_value(c);
+        if (value & BEST_MASK) {
+            v = std::max((proto::get_value(c) & ~BEST_MASK) + 1, v);
+            for (size_t i = 0; i < counters.size(); ++i) {
+                if (proto::get_id(counters[i]) == id) {
+                    counter = &counters[i];
+                    best_index = i;
+                    break;
+                }
             }
         }
     }
-    if (best_index == undef) {
-        counters.emplace_back(proto::Counter());
-        counter = &counters.back();
-        proto::set_id(*counter, id);
-        best_index = &counters.back() - counters.data();
+    if (best_index < 0) {
+        auto copy = proto::Counter(id, v | BEST_MASK);
+        auto new_sz = counters.size();
+        counters.resize(new_sz + 1);
+        counters[new_sz] = std::move(copy);
+        best_index = new_sz;
+    } else {
+        assert(counter);
+        proto::set_value(*counter, v | BEST_MASK);
     }
-    proto::set_value(*counter, v);
-}
-
-auto version_t::get_best() noexcept -> proto::Counter & {
-    assert(best_index != undef);
-    return counters[best_index];
 }
 
-auto version_t::get_best() const noexcept -> const proto::Counter & {
-    assert(best_index != undef);
-    return counters[best_index];
+auto version_t::get_best() const noexcept -> proto::Counter {
+    auto r = proto::Counter();
+    for (auto &c : counters) {
+        auto value = proto::get_value(c);
+        if (value & BEST_MASK) {
+            r = proto::Counter{proto::get_id(c), value & ~BEST_MASK};
+        }
+    }
+    return r;
 }
 
 bool version_t::contains(const version_t &other) const noexcept {
-    auto &other_best = other.get_best();
+    auto other_best = other.get_best();
     for (size_t i = 0; i < counters.size(); ++i) {
         auto &c = counters[i];
-        auto ids_match = proto::get_id(c) == proto::get_id(other_best);
+        auto id_my = proto::get_id(c);
+        auto id_other = proto::get_id(other_best);
+        auto ids_match = id_my == id_other;
         if (ids_match) {
-            return proto::get_value(c) >= proto::get_value(other_best);
+            auto value_my = proto::get_value(c) & ~BEST_MASK;
+            auto value_other = proto::get_value(other_best);
+            return value_my >= value_other;
         }
     }
     return false;
@@ -101,7 +114,9 @@ bool version_t::identical_to(const version_t &other) const noexcept {
         auto end = p1 + counters.size();
         while (p1 != end) {
             auto ids_match = proto::get_id(*p1) == proto::get_id(*p2);
-            auto values_match = proto::get_value(*p1) == proto::get_value(*p2);
+            auto v1 = proto::get_value(*p1) & ~BEST_MASK;
+            auto v2 = proto::get_value(*p2) & ~BEST_MASK;
+            auto values_match = v1 == v2;
             if (ids_match && values_match) {
                 ++p1;
                 ++p2;
@@ -121,4 +136,13 @@ auto version_t::get_counter(size_t index) noexcept -> const proto::Counter & {
     return counters[index];
 }
 
-auto version_t::get_counters() noexcept -> const counters_t & { return counters; }
+auto version_t::get_counters() const noexcept -> counters_t {
+    auto copy = counters_t();
+    copy.resize(counters.size());
+    for (std::uint32_t i = 0; i < counters.sz; ++i) {
+        auto id = proto::get_id(counters[i]);
+        auto value = proto::get_value(counters[i]) & ~BEST_MASK;
+        copy[i] = proto::Counter(id, value);
+    }
+    return counters;
+}

+ 0 - 0
src/model/version.h


Algunos archivos no se mostraron porque demasiados archivos cambiaron en este cambio