Line data Source code
1 : /**
2 : * Copyright Soramitsu Co., Ltd. All Rights Reserved.
3 : * SPDX-License-Identifier: Apache-2.0
4 : */
5 :
6 : #include "ametsuchi/impl/mutable_storage_impl.hpp"
7 :
8 : #include <boost/variant/apply_visitor.hpp>
9 : #include "ametsuchi/impl/peer_query_wsv.hpp"
10 : #include "ametsuchi/impl/postgres_block_index.hpp"
11 : #include "ametsuchi/impl/postgres_command_executor.hpp"
12 : #include "ametsuchi/impl/postgres_wsv_command.hpp"
13 : #include "ametsuchi/impl/postgres_wsv_query.hpp"
14 : #include "interfaces/commands/command.hpp"
15 : #include "interfaces/common_objects/common_objects_factory.hpp"
16 :
17 : namespace iroha {
18 : namespace ametsuchi {
19 : MutableStorageImpl::MutableStorageImpl(
20 : shared_model::interface::types::HashType top_hash,
21 : std::shared_ptr<PostgresCommandExecutor> cmd_executor,
22 : std::unique_ptr<soci::session> sql,
23 : std::shared_ptr<shared_model::interface::CommonObjectsFactory> factory)
24 539 : : top_hash_(top_hash),
25 539 : sql_(std::move(sql)),
26 539 : peer_query_(std::make_unique<PeerQueryWsv>(
27 539 : std::make_shared<PostgresWsvQuery>(*sql_, std::move(factory)))),
28 539 : block_index_(std::make_unique<PostgresBlockIndex>(*sql_)),
29 539 : command_executor_(std::move(cmd_executor)),
30 539 : committed(false),
31 539 : log_(logger::log("MutableStorage")) {
32 539 : *sql_ << "BEGIN";
33 539 : }
34 :
35 : bool MutableStorageImpl::apply(const shared_model::interface::Block &block,
36 : MutableStoragePredicate predicate) {
37 : auto execute_transaction = [this](auto &transaction) {
38 566 : command_executor_->setCreatorAccountId(transaction.creatorAccountId());
39 566 : command_executor_->doValidation(false);
40 :
41 : auto execute_command = [this](const auto &command) {
42 : auto command_applied =
43 4060 : boost::apply_visitor(*command_executor_, command.get());
44 :
45 4060 : return command_applied.match(
46 : [](expected::Value<void> &) { return true; },
47 : [&](expected::Error<CommandError> &e) {
48 0 : log_->error(e.error.toString());
49 0 : return false;
50 0 : });
51 4060 : };
52 :
53 566 : return std::all_of(transaction.commands().begin(),
54 566 : transaction.commands().end(),
55 566 : execute_command);
56 0 : };
57 :
58 542 : log_->info("Applying block: height {}, hash {}",
59 542 : block.height(),
60 542 : block.hash().hex());
61 :
62 542 : auto block_applied = predicate(block, *peer_query_, top_hash_)
63 542 : and std::all_of(block.transactions().begin(),
64 540 : block.transactions().end(),
65 540 : execute_transaction);
66 542 : if (block_applied) {
67 540 : block_store_.insert(std::make_pair(block.height(), clone(block)));
68 540 : block_index_->index(block);
69 :
70 540 : top_hash_ = block.hash();
71 540 : }
72 :
73 542 : return block_applied;
74 0 : }
75 :
76 : template <typename Function>
77 : bool MutableStorageImpl::withSavepoint(Function &&function) {
78 536 : *sql_ << "SAVEPOINT savepoint_";
79 :
80 536 : auto function_executed = std::forward<Function>(function)();
81 :
82 : if (function_executed) {
83 536 : *sql_ << "RELEASE SAVEPOINT savepoint_";
84 536 : } else {
85 2 : *sql_ << "ROLLBACK TO SAVEPOINT savepoint_";
86 : }
87 :
88 536 : return function_executed;
89 : }
90 :
91 : bool MutableStorageImpl::apply(
92 : const shared_model::interface::Block &block) {
93 : return withSavepoint([&] {
94 536 : return this->apply(
95 : block, [](const auto &, auto &, const auto &) { return true; });
96 0 : });
97 : }
98 :
99 : bool MutableStorageImpl::apply(
100 : rxcpp::observable<std::shared_ptr<shared_model::interface::Block>>
101 : blocks,
102 : MutableStoragePredicate predicate) {
103 : return withSavepoint([&] {
104 4 : return blocks
105 : .all([&](auto block) { return this->apply(*block, predicate); })
106 4 : .as_blocking()
107 4 : .first();
108 0 : });
109 : }
110 :
111 : MutableStorageImpl::~MutableStorageImpl() {
112 : if (not committed) {
113 4 : *sql_ << "ROLLBACK";
114 4 : }
115 539 : }
116 : } // namespace ametsuchi
117 : } // namespace iroha
|