diff --git a/validator/db/archive-manager.cpp b/validator/db/archive-manager.cpp index d8a079721..14b6515f8 100644 --- a/validator/db/archive-manager.cpp +++ b/validator/db/archive-manager.cpp @@ -604,6 +604,7 @@ void ArchiveManager::load_package(PackageId id) { td::actor::create_actor("slice", id.id, id.key, id.temp, false, db_root_, archive_lru_.get()); m.emplace(id, std::move(desc)); + update_permanent_slices(); } const ArchiveManager::FileDescription *ArchiveManager::get_file_desc(ShardIdFull shard, PackageId id, BlockSeqno seqno, @@ -677,6 +678,7 @@ const ArchiveManager::FileDescription *ArchiveManager::add_file_desc(ShardIdFull .ensure(); } index_->commit_transaction().ensure(); + update_permanent_slices(); return &desc; } @@ -1207,6 +1209,7 @@ void ArchiveManager::truncate(BlockSeqno masterchain_seqno, ConstBlockHandle han } } } + update_permanent_slices(); } void ArchiveManager::FileMap::shard_index_add(const FileDescription &desc) { @@ -1305,6 +1308,23 @@ const ArchiveManager::FileDescription *ArchiveManager::FileMap::get_next_file_de return it2->second->deleted ? nullptr : it2->second; } +void ArchiveManager::update_permanent_slices() { + if (archive_lru_.empty()) { + return; + } + std::vector ids; + if (!files_.empty()) { + ids.push_back(files_.rbegin()->first); + } + if (!key_files_.empty()) { + ids.push_back(key_files_.rbegin()->first); + } + if (!temp_files_.empty()) { + ids.push_back(temp_files_.rbegin()->first); + } + td::actor::send_closure(archive_lru_, &ArchiveLru::set_permanent_slices, std::move(ids)); +} + } // namespace validator } // namespace ton diff --git a/validator/db/archive-manager.hpp b/validator/db/archive-manager.hpp index 138d8b36d..3f17069c0 100644 --- a/validator/db/archive-manager.hpp +++ b/validator/db/archive-manager.hpp @@ -123,6 +123,9 @@ class ArchiveManager : public td::actor::Actor { size_t size() const { return files_.size(); } + bool empty() const { + return files_.empty(); + } std::map::const_iterator lower_bound(const PackageId &x) const { return files_.lower_bound(x); } @@ -217,6 +220,8 @@ class ArchiveManager : public td::actor::Actor { PackageId get_temp_package_id() const; PackageId get_key_package_id(BlockSeqno seqno) const; PackageId get_temp_package_id_by_unixtime(UnixTime ts) const; + + void update_permanent_slices(); }; } // namespace validator diff --git a/validator/db/archive-slice.cpp b/validator/db/archive-slice.cpp index 08cd97fc3..4a7c419a9 100644 --- a/validator/db/archive-slice.cpp +++ b/validator/db/archive-slice.cpp @@ -900,23 +900,58 @@ void ArchiveSlice::truncate(BlockSeqno masterchain_seqno, ConstBlockHandle handl promise.set_value(td::Unit()); } +static std::tuple to_tuple(const PackageId &id) { + return {id.id, id.temp, id.key}; +} + void ArchiveLru::on_query(td::actor::ActorId slice, PackageId id, size_t files_count) { - SliceInfo &info = open_slices_[id]; - if (info.lru_idx != 0) { + SliceInfo &info = slices_[to_tuple(id)]; + if (info.opened_idx != 0) { total_files_ -= info.files_count; - lru_.erase(info.lru_idx); + lru_.erase(info.opened_idx); } info.actor = std::move(slice); total_files_ += (info.files_count = files_count); - lru_.emplace(info.lru_idx = current_idx_++, id); + info.opened_idx = current_idx_++; + if (!info.is_permanent) { + lru_.emplace(info.opened_idx, id); + } + enforce_limit(); +} + +void ArchiveLru::set_permanent_slices(std::vector ids) { + for (auto id : permanent_slices_) { + SliceInfo &info = slices_[to_tuple(id)]; + if (!info.is_permanent) { + continue; + } + info.is_permanent = false; + if (info.opened_idx) { + lru_.emplace(info.opened_idx, id); + } + } + permanent_slices_ = std::move(ids); + for (auto id : permanent_slices_) { + SliceInfo &info = slices_[to_tuple(id)]; + if (info.is_permanent) { + continue; + } + info.is_permanent = true; + if (info.opened_idx) { + lru_.erase(info.opened_idx); + } + } + enforce_limit(); +} +void ArchiveLru::enforce_limit() { while (total_files_ > max_total_files_ && lru_.size() > 1) { auto it = lru_.begin(); - auto it2 = open_slices_.find(it->second); + auto it2 = slices_.find(to_tuple(it->second)); lru_.erase(it); total_files_ -= it2->second.files_count; td::actor::send_closure(it2->second.actor, &ArchiveSlice::close_files); - open_slices_.erase(it2); + it2->second.opened_idx = 0; } } diff --git a/validator/db/archive-slice.hpp b/validator/db/archive-slice.hpp index a1a9df461..9f775d2ec 100644 --- a/validator/db/archive-slice.hpp +++ b/validator/db/archive-slice.hpp @@ -196,17 +196,22 @@ class ArchiveLru : public td::actor::Actor { CHECK(max_total_files_ > 0); } void on_query(td::actor::ActorId slice, PackageId id, size_t files_count); + void set_permanent_slices(std::vector ids); private: size_t current_idx_ = 1; struct SliceInfo { td::actor::ActorId actor; size_t files_count = 0; - size_t lru_idx = 0; + size_t opened_idx = 0; // 0 - not opened + bool is_permanent = false; }; - std::map open_slices_; + std::map, SliceInfo> slices_; std::map lru_; size_t total_files_ = 0; size_t max_total_files_ = 0; + std::vector permanent_slices_; + + void enforce_limit(); }; } // namespace validator