/*
    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 .
    Copyright 2017-2020 Telegram Systems LLP
*/
#pragma once
#include "vm/cellslice.h"
#include "vm/cells.h"
#include "vm/boc.h"
#include "td/db/KeyValue.h"
#include "vm/db/CellStorage.h"
#include "vm/db/CellHashTable.h"
#include "td/utils/Slice.h"
#include "td/utils/Status.h"
namespace vm {
class SmartContractDbImpl;
using SmartContractDb = std::unique_ptr;
using KeyValue = td::KeyValue;
using KeyValueReader = td::KeyValueReader;
struct SmartContractMeta {
  DynamicBagOfCellsDb::Stats stats;
  enum BagOfCellsType { Dynamic, Static } type{Static};
  template 
  void store(StorerT &storer) const;
  template 
  void parse(ParserT &parser);
};
class SmartContractDbImpl {
 public:
  Ref| get_root();
  SmartContractMeta get_meta();
  td::Status validate_meta();
  void set_root(Ref | new_root);
  SmartContractDbImpl(td::Slice hash, std::shared_ptr kv);
 private:
  std::string hash_;
  std::shared_ptr kv_;
  bool sync_root_with_db_{false};
  Ref | db_root_;
  Ref | new_root_;
  SmartContractMeta meta_;
  bool is_dynamic_commit_;
  std::string boc_to_commit_;
  std::unique_ptr cell_db_;
  std::unique_ptr bag_of_cells_;
  friend class SmartContractDiff;
  friend class TonDbTransactionImpl;
  void sync_root_with_db();
  td::Slice hash() const {
    return hash_;
  }
  void prepare_transaction();
  void commit_transaction(KeyValue &kv);
  void set_reader(std::shared_ptr reader);
  bool is_dynamic() const;
  void prepare_commit_dynamic(bool force);
  void prepare_commit_static(bool force);
  bool is_root_changed() const;
};
class SmartContractDiff {
 public:
  explicit SmartContractDiff(SmartContractDb db) : db_(std::move(db)) {
    db_->prepare_transaction();
  }
  SmartContractDb extract_smartcontract() {
    return std::move(db_);
  }
  td::Slice hash() const {
    return db_->hash();
  }
  void commit_transaction(KeyValue &kv) {
    db_->commit_transaction(kv);
  }
 private:
  SmartContractDb db_;
};
class TonDbTransactionImpl;
using TonDbTransaction = std::unique_ptr;
class TonDbTransactionImpl {
 public:
  SmartContractDb begin_smartcontract(td::Slice hash = {});
  void commit_smartcontract(SmartContractDb txn);
  void commit_smartcontract(SmartContractDiff txn);
  void abort_smartcontract(SmartContractDb txn);
  void abort_smartcontract(SmartContractDiff txn);
  TonDbTransactionImpl(std::shared_ptr kv);
 private:
  std::shared_ptr kv_;
  std::shared_ptr reader_;
  td::uint64 generation_{0};
  struct SmartContractInfo {
    bool is_inited{false};
    td::uint64 generation_{0};
    std::string hash;
    SmartContractDb smart_contract_db;
    bool operator<(const SmartContractInfo &other) const {
      return hash < other.hash;
    }
    friend bool operator<(const SmartContractInfo &info, td::Slice hash) {
      return info.hash < hash;
    }
    friend bool operator<(td::Slice hash, const SmartContractInfo &info) {
      return hash < info.hash;
    }
  };
  CellHashTable contracts_;
  KeyValue &kv() {
    return *kv_;
  }
  friend class TonDbImpl;
  void begin();
  void commit();
  void abort();
  void clear_cache();
  void end_smartcontract(SmartContractDb smart_contract);
};
class TonDbImpl;
using TonDb = std::unique_ptr;
class TonDbImpl {
 public:
  TonDbImpl(std::unique_ptr kv);
  ~TonDbImpl();
  TonDbTransaction begin_transaction();
  void commit_transaction(TonDbTransaction transaction);
  void abort_transaction(TonDbTransaction transaction);
  void clear_cache();
  static td::Result open(td::Slice path);
  std::string stats() const;
 private:
  std::shared_ptr kv_;
  TonDbTransaction transaction_;
};
}  // namespace vm |  |  |  |