mirror of
				https://github.com/ton-blockchain/ton
				synced 2025-03-09 15:40:10 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			135 lines
		
	
	
	
		
			5.1 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			135 lines
		
	
	
	
		
			5.1 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/>.
 | |
| 
 | |
|     Copyright 2017-2019 Telegram Systems LLP
 | |
| */
 | |
| #pragma once
 | |
| #include <string>
 | |
| #include <map>
 | |
| #include "vm/cells.h"
 | |
| #include "block/Binlog.h"
 | |
| #include "block/block-db.h"
 | |
| #include "block/block-binlog.h"
 | |
| 
 | |
| namespace block {
 | |
| using td::Ref;
 | |
| 
 | |
| /*
 | |
|  * 
 | |
|  *   BLOCK DATABASE
 | |
|  * 
 | |
|  */
 | |
| 
 | |
| class BlockDbImpl;
 | |
| 
 | |
| class BlockBinlogCallback : public BinlogCallback {
 | |
|   BlockDbImpl& db;
 | |
|   td::Status init_new_binlog(BinlogBuffer& bb) override;
 | |
|   int replay_log_event(BinlogBuffer& bb, const unsigned* ptr, std::size_t len, unsigned long long log_pos) override;
 | |
|   int replay(const block::log::Start& lev, unsigned long long log_pos) const;
 | |
|   int replay(const block::log::SetZeroState& lev, unsigned long long log_pos) const;
 | |
|   int replay(const block::log::NewBlock& lev, unsigned long long log_pos) const;
 | |
|   int replay(const block::log::NewState& lev, unsigned long long log_pos) const;
 | |
|   template <typename T>
 | |
|   inline int try_interpret(const unsigned* ptr, std::size_t len, unsigned long long log_pos);
 | |
| 
 | |
|  public:
 | |
|   BlockBinlogCallback(BlockDbImpl& _db) : db(_db) {
 | |
|   }
 | |
| };
 | |
| 
 | |
| template <typename T>
 | |
| inline int BlockBinlogCallback::try_interpret(const unsigned* ptr, std::size_t len, unsigned long long log_pos) {
 | |
|   if (len < sizeof(T)) {
 | |
|     return 0x80000000 + sizeof(T);
 | |
|   } else {
 | |
|     int res = replay(*reinterpret_cast<const T*>(ptr), log_pos);
 | |
|     return res >= 0 ? sizeof(T) : res;
 | |
|   }
 | |
| }
 | |
| 
 | |
| class BlockDbImpl final : public BlockDb {
 | |
|   int status;
 | |
|   bool allow_uninit;
 | |
|   bool created;
 | |
|   int depth;
 | |
|   std::unique_ptr<ZerostateInfo> zstate;
 | |
|   std::string base_dir;
 | |
|   std::string binlog_name;
 | |
|   BinlogBuffer bb;
 | |
|   ton::Bits256 zstate_rhash, zstate_fhash;
 | |
|   unsigned created_at;
 | |
|   std::map<ton::FileHash, td::BufferSlice> file_cache;
 | |
|   std::map<ton::BlockId, Ref<FileInfo>> block_info;
 | |
|   std::map<ton::BlockId, Ref<FileInfo>> state_info;
 | |
|   //
 | |
|   td::Result<int> do_init();
 | |
| 
 | |
|  public:
 | |
|   enum FMode {
 | |
|     chk_none = 0,
 | |
|     chk_if_exists = 1,
 | |
|     fail_if_exists = 2,
 | |
|     overwrite = 4,
 | |
|     chk_size_only = 16,
 | |
|     chk_file_hash = 32
 | |
|   };
 | |
|   static constexpr const char* default_binlog_name = "blockdb";
 | |
|   static constexpr const char* default_binlog_suffix = ".bin";
 | |
|   static constexpr int default_depth = 4;
 | |
|   BlockDbImpl(td::Result<int>& _res, std::string _base_dir, std::unique_ptr<ZerostateInfo> _zstate = nullptr,
 | |
|               bool _allow_uninit = false, int _depth = 4, std::string _binlog_name = "");
 | |
|   ~BlockDbImpl();
 | |
|   bool ok() const {
 | |
|     return status >= 0;
 | |
|   }
 | |
|   bool initialized() const {
 | |
|     return status != 0;
 | |
|   }
 | |
|   bool init_ok() const {
 | |
|     return status > 0;
 | |
|   }
 | |
| 
 | |
|  protected:
 | |
|   friend class BlockBinlogCallback;
 | |
|   td::Ref<FileInfo> zerostate;
 | |
|   td::Status init_from_zstate();
 | |
|   td::Status update_block_info(Ref<FileInfo> blk_info);
 | |
|   td::Status update_state_info(Ref<FileInfo> state);
 | |
| 
 | |
|  private:
 | |
|   std::string compute_db_filename(const FileHash& file_hash) const;
 | |
|   std::string compute_db_tmp_filename(const FileHash& file_hash, int i, bool makedirs) const;
 | |
|   td::Status save_db_file(const FileHash& file_hash, const td::BufferSlice& data, int fmode = 0);
 | |
|   td::Status load_data(FileInfo& file_info, bool force = false);
 | |
|   // actor BlockDb implementation
 | |
|   void get_top_block_id(ton::ShardIdFull shard, int authority, td::Promise<ton::BlockIdExt> promise) override;
 | |
|   void get_top_block_state_id(ton::ShardIdFull shard, int authority, td::Promise<ton::BlockIdExt> promise) override;
 | |
|   void get_block_by_id(ton::BlockId blk_id, bool need_data, td::Promise<td::Ref<FileInfo>> promise) override;
 | |
|   void get_state_by_id(ton::BlockId blk_id, bool need_data, td::Promise<td::Ref<FileInfo>> promise) override;
 | |
|   void get_out_queue_info_by_id(ton::BlockId blk_id, td::Promise<td::Ref<OutputQueueInfoDescr>> promise) override;
 | |
|   void get_object_by_file_hash(FileHash file_hash, bool need_data, bool force_file_load,
 | |
|                                td::Promise<td::Ref<FileInfo>> promise) override;
 | |
|   void get_object_by_root_hash(RootHash root_hash, bool need_data, bool force_file_load,
 | |
|                                td::Promise<td::Ref<FileInfo>> promise) override;
 | |
|   void save_new_block(ton::BlockIdExt blk_id, td::BufferSlice data, int authority,
 | |
|                       td::Promise<td::Unit> promise) override;
 | |
|   void save_new_state(ton::BlockIdExt state_id, td::BufferSlice data, int authority,
 | |
|                       td::Promise<td::Unit> promise) override;
 | |
|   bool file_cache_insert(const FileHash& file_hash, const td::BufferSlice& data, int mode = 0);
 | |
| };
 | |
| 
 | |
| }  // namespace block
 |