mirror of
				https://github.com/ton-blockchain/ton
				synced 2025-03-09 15:40:10 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			116 lines
		
	
	
	
		
			3.5 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			116 lines
		
	
	
	
		
			3.5 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| /*
 | |
|     This file is part of TON Blockchain Library.
 | |
| 
 | |
|     TON Blockchain Library is free software: you can redistribute it and/or modify
 | |
|     it under the terms of the GNU Lesser General Public License as published by
 | |
|     the Free Software Foundation, either version 2 of the License, or
 | |
|     (at your option) any later version.
 | |
| 
 | |
|     TON Blockchain Library 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 Lesser General Public License for more details.
 | |
| 
 | |
|     You should have received a copy of the GNU Lesser General Public License
 | |
|     along with TON Blockchain Library.  If not, see <http://www.gnu.org/licenses/>.
 | |
| */
 | |
| #pragma once
 | |
| 
 | |
| #include "interfaces/liteserver.h"
 | |
| #include <map>
 | |
| 
 | |
| namespace ton::validator {
 | |
| 
 | |
| class LiteServerCacheImpl : public LiteServerCache {
 | |
|  public:
 | |
|   void start_up() override {
 | |
|     alarm();
 | |
|   }
 | |
| 
 | |
|   void alarm() override {
 | |
|     alarm_timestamp() = td::Timestamp::in(60.0);
 | |
|     if (queries_cnt_ > 0 || !send_message_cache_.empty()) {
 | |
|       LOG(WARNING) << "LS Cache stats: " << queries_cnt_ << " queries, " << queries_hit_cnt_ << " hits; "
 | |
|                    << cache_.size() << " entries, size=" << total_size_ << "/" << MAX_CACHE_SIZE << ";   "
 | |
|                    << send_message_cache_.size() << " different sendMessage queries, " << send_message_error_cnt_
 | |
|                    << " duplicates";
 | |
|       queries_cnt_ = 0;
 | |
|       queries_hit_cnt_ = 0;
 | |
|       send_message_cache_.clear();
 | |
|       send_message_error_cnt_ = 0;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   void lookup(td::Bits256 key, td::Promise<td::BufferSlice> promise) override {
 | |
|     ++queries_cnt_;
 | |
|     auto it = cache_.find(key);
 | |
|     if (it == cache_.end()) {
 | |
|       promise.set_error(td::Status::Error("not found"));
 | |
|       return;
 | |
|     }
 | |
|     ++queries_hit_cnt_;
 | |
|     auto entry = it->second.get();
 | |
|     entry->remove();
 | |
|     lru_.put(entry);
 | |
|     promise.set_value(entry->value_.clone());
 | |
|   }
 | |
| 
 | |
|   void update(td::Bits256 key, td::BufferSlice value) override {
 | |
|     std::unique_ptr<CacheEntry> &entry = cache_[key];
 | |
|     if (entry == nullptr) {
 | |
|       entry = std::make_unique<CacheEntry>(key, std::move(value));
 | |
|     } else {
 | |
|       total_size_ -= entry->size();
 | |
|       entry->value_ = std::move(value);
 | |
|       entry->remove();
 | |
|     }
 | |
|     lru_.put(entry.get());
 | |
|     total_size_ += entry->size();
 | |
| 
 | |
|     while (total_size_ > MAX_CACHE_SIZE) {
 | |
|       auto to_remove = (CacheEntry *)lru_.get();
 | |
|       CHECK(to_remove);
 | |
|       total_size_ -= to_remove->size();
 | |
|       to_remove->remove();
 | |
|       cache_.erase(to_remove->key_);
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   void process_send_message(td::Bits256 key, td::Promise<td::Unit> promise) override {
 | |
|     if (send_message_cache_.insert(key).second) {
 | |
|       promise.set_result(td::Unit());
 | |
|     } else {
 | |
|       ++send_message_error_cnt_;
 | |
|       promise.set_error(td::Status::Error("duplicate message"));
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   void drop_send_message_from_cache(td::Bits256 key) override {
 | |
|     send_message_cache_.erase(key);
 | |
|   }
 | |
| 
 | |
|  private:
 | |
|   struct CacheEntry : public td::ListNode {
 | |
|     explicit CacheEntry(td::Bits256 key, td::BufferSlice value) : key_(key), value_(std::move(value)) {
 | |
|     }
 | |
|     td::Bits256 key_;
 | |
|     td::BufferSlice value_;
 | |
| 
 | |
|     size_t size() const {
 | |
|       return value_.size() + 32 * 2;
 | |
|     }
 | |
|   };
 | |
| 
 | |
|   std::map<td::Bits256, std::unique_ptr<CacheEntry>> cache_;
 | |
|   td::ListNode lru_;
 | |
|   size_t total_size_ = 0;
 | |
| 
 | |
|   size_t queries_cnt_ = 0, queries_hit_cnt_ = 0;
 | |
| 
 | |
|   std::set<td::Bits256> send_message_cache_;
 | |
|   size_t send_message_error_cnt_ = 0;
 | |
| 
 | |
|   static constexpr size_t MAX_CACHE_SIZE = 64 << 20;
 | |
| };
 | |
| 
 | |
| }  // namespace ton::validator
 |