github.com/igggame/nebulas-go@v2.1.0+incompatible/nbre/cmd/dummy_neb/generator/generator_base.cpp (about)

     1  // Copyright (C) 2018 go-nebulas authors
     2  //
     3  // This file is part of the go-nebulas library.
     4  //
     5  // the go-nebulas library is free software: you can redistribute it and/or
     6  // modify
     7  // it under the terms of the GNU General Public License as published by
     8  // the Free Software Foundation, either version 3 of the License, or
     9  // (at your option) any later version.
    10  //
    11  // the go-nebulas library is distributed in the hope that it will be useful,
    12  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    13  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    14  // GNU General Public License for more details.
    15  //
    16  // You should have received a copy of the GNU General Public License
    17  // along with the go-nebulas library.  If not, see
    18  // <http://www.gnu.org/licenses/>.
    19  //
    20  #include "cmd/dummy_neb/generator/generator_base.h"
    21  
    22  uint64_t checker_task_base::s_task_id = 0;
    23  
    24  checker_task_base::checker_task_base()
    25      : m_task_id(s_task_id++), m_last_call_timepoint(), m_call_times(0),
    26        m_b_is_running(false){};
    27  
    28  checker_task_base::~checker_task_base() {}
    29  
    30  std::string checker_task_base::name() const { return ""; }
    31  
    32  void checker_task_base::apply_result(const std::string &result) {
    33    std::unique_lock<std::mutex> _l(m_mutex);
    34    m_exist_results.insert(result);
    35    m_last_call_timepoint = std::chrono::steady_clock::now();
    36    m_call_times++;
    37    m_b_is_running = false;
    38  }
    39  
    40  std::string checker_task_base::status() const {
    41    std::unique_lock<std::mutex> _l(m_mutex);
    42    std::stringstream ss;
    43    ss << "->" << name() << " called " << m_call_times << " times, with "
    44       << m_exist_results.size() << " diff results. \n";
    45    for (auto &s : m_exist_results) {
    46      ss << "\t\t" << s << '\n';
    47    }
    48    return ss.str();
    49  }
    50  #if 0
    51  void checker_tasks::init_from_db() {
    52    try {
    53      std::string s =
    54          bc_storage_session::instance().get_string(get_all_checker_info_key());
    55      checker_marshaler cm;
    56      cm.deserialize_from_string(s);
    57      for (auto &sub_s : cm.get<p_checkers>()) {
    58        checker_marshaler sub_cm;
    59        sub_cm.deserialize_from_string(sub_s);
    60        for (auto &cs : sub_cm.get<p_checkers>()) {
    61          auto checker = init_checker_from_string(cs);
    62          add_task(checker);
    63        }
    64      }
    65    } catch (...) {
    66    }
    67  }
    68  
    69  void checker_tasks::write_to_db() {
    70    checker_marshaler cm;
    71    for (auto &it : m_all_tasks) {
    72      cm.get<p_checkers>().push_back(it.first);
    73      checker_marshaler sub_cm;
    74      for (auto ik : *(it.second)) {
    75        sub_cm.get<p_checkers>().push_back(ik->serialize_to_string());
    76      }
    77      std::string ss = sub_cm.serialize_to_string();
    78      bc_storage_session::instance().put(get_checker_key_with_name(it.first), ss);
    79    }
    80    std::string s = cm.serialize_to_string();
    81    bc_storage_session::instance().put(get_all_checker_info_key(), s);
    82  }
    83  #endif
    84  
    85  void checker_tasks::add_task(const std::shared_ptr<checker_task_base> &task) {
    86    if (!task)
    87      return;
    88    std::unique_lock<std::mutex> _l(m_mutex);
    89    m_all_tasks.insert(std::make_pair(task->task_id(), task));
    90  }
    91  void checker_tasks::randomly_schedule_no_running_tasks() {
    92    std::unique_lock<std::mutex> _l(m_mutex);
    93    std::vector<uint64_t> keys;
    94    for (auto &kv : m_all_tasks) {
    95      keys.push_back(kv.first);
    96    }
    97    if (keys.size() == 0)
    98      return;
    99    uint64_t k = keys[std::rand() % keys.size()];
   100    uint64_t max_num = 16;
   101    uint64_t i = 0;
   102    while (m_all_tasks[k]->is_running()) {
   103      if (i > max_num) {
   104        return;
   105      }
   106      i++;
   107      k = keys[std::rand() % keys.size()];
   108    }
   109    std::shared_ptr<checker_task_base> task = m_all_tasks[k];
   110    // task->check();
   111    task_executor::instance().schedule([task]() { task->check(); });
   112  }
   113  
   114  void checker_tasks::randomly_schedule_all_tasks(int num) {
   115    std::unique_lock<std::mutex> _l(m_mutex);
   116    std::vector<uint64_t> keys;
   117    for (auto &kv : m_all_tasks) {
   118      keys.push_back(kv.first);
   119    }
   120    if (keys.empty())
   121      return;
   122    for (int i = 0; i < num; ++i) {
   123      uint64_t k = keys[std::rand() % keys.size()];
   124      auto task = m_all_tasks[k];
   125      task_executor::instance().schedule([task]() { task->check(); });
   126    }
   127  }
   128  
   129  std::string checker_tasks::status() const {
   130    std::unique_lock<std::mutex> _l(m_mutex);
   131  
   132    std::stringstream ss;
   133    ss << m_all_tasks.size() << "tasks in total.\n";
   134    for (auto &kv : m_all_tasks) {
   135      ss << kv.second->status();
   136    }
   137    return ss.str();
   138  }
   139  
   140  std::shared_ptr<checker_task_base>
   141  init_checker_from_string(const std::string &s) {
   142  #define add_type(type)                                                         \
   143    if (type().name() == s) {                                                    \
   144      auto t = std::make_shared<type>();                                         \
   145      t->deserialize_from_string(s);                                             \
   146      return t;                                                                  \
   147    }
   148    return nullptr;
   149  
   150  #undef add_type
   151  }
   152  
   153  generator_base::generator_base(all_accounts *accounts, generate_block *block,
   154                                 int new_account_num, int tx_num)
   155      : m_all_accounts(accounts), m_block(block),
   156        m_new_account_num(new_account_num), m_new_tx_num(tx_num) {}
   157  
   158  void generator_base::run() {
   159    for (int i = 0; i < m_new_account_num; ++i) {
   160      gen_account();
   161    }
   162    for (int i = 0; i < m_new_tx_num; ++i) {
   163      gen_tx();
   164    }
   165  
   166    auto checkers = gen_tasks();
   167    if (!checkers)
   168      return;
   169    for (auto &checker : *checkers) {
   170      checker_tasks::instance().add_task(checker);
   171    }
   172  }