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/postgres_block_query.hpp"
7 :
8 : #include <boost/format.hpp>
9 : #include <boost/range/adaptor/transformed.hpp>
10 : #include <boost/range/algorithm/for_each.hpp>
11 :
12 : #include "ametsuchi/impl/soci_utils.hpp"
13 : #include "common/byteutils.hpp"
14 : #include "logger/logger.hpp"
15 :
16 : namespace iroha {
17 : namespace ametsuchi {
18 : PostgresBlockQuery::PostgresBlockQuery(
19 : soci::session &sql,
20 : KeyValueStorage &file_store,
21 : std::shared_ptr<shared_model::interface::BlockJsonDeserializer>
22 : converter,
23 : logger::LoggerPtr log)
24 26 : : sql_(sql),
25 26 : block_store_(file_store),
26 26 : converter_(std::move(converter)),
27 26 : log_(std::move(log)) {}
28 :
29 : PostgresBlockQuery::PostgresBlockQuery(
30 : std::unique_ptr<soci::session> sql,
31 : KeyValueStorage &file_store,
32 : std::shared_ptr<shared_model::interface::BlockJsonDeserializer>
33 : converter,
34 : logger::LoggerPtr log)
35 8061 : : psql_(std::move(sql)),
36 8066 : sql_(*psql_),
37 8066 : block_store_(file_store),
38 8066 : converter_(std::move(converter)),
39 8067 : log_(std::move(log)) {}
40 :
41 : std::vector<BlockQuery::wBlock> PostgresBlockQuery::getBlocks(
42 : shared_model::interface::types::HeightType height, uint32_t count) {
43 505 : shared_model::interface::types::HeightType last_id =
44 505 : block_store_.last_id();
45 505 : auto to = std::min(last_id, height + count - 1);
46 505 : std::vector<BlockQuery::wBlock> result;
47 505 : if (height > to or count == 0) {
48 2 : return result;
49 : }
50 1011 : for (auto i = height; i <= to; i++) {
51 508 : auto block = getBlock(i);
52 508 : block.match(
53 : [&result](
54 : expected::Value<std::unique_ptr<shared_model::interface::Block>>
55 505 : &v) { result.emplace_back(std::move(v.value)); },
56 : [this](const expected::Error<std::string> &e) {
57 3 : log_->error(e.error);
58 3 : });
59 508 : }
60 503 : return result;
61 505 : }
62 :
63 : std::vector<BlockQuery::wBlock> PostgresBlockQuery::getBlocksFrom(
64 : shared_model::interface::types::HeightType height) {
65 249 : return getBlocks(height, block_store_.last_id());
66 : }
67 :
68 : std::vector<BlockQuery::wBlock> PostgresBlockQuery::getTopBlocks(
69 : uint32_t count) {
70 248 : auto last_id = block_store_.last_id();
71 248 : count = std::min(count, last_id);
72 248 : return getBlocks(last_id - count + 1, count);
73 : }
74 :
75 : boost::optional<TxCacheStatusType> PostgresBlockQuery::checkTxPresence(
76 : const shared_model::crypto::Hash &hash) {
77 5166 : int res = -1;
78 5166 : const auto &hash_str = hash.hex();
79 :
80 : try {
81 5201 : sql_ << "SELECT status FROM tx_status_by_hash WHERE hash = :hash",
82 5296 : soci::into(res), soci::use(hash_str);
83 5250 : } catch (const std::exception &e) {
84 0 : log_->error("Failed to execute query: {}", e.what());
85 0 : return boost::none;
86 0 : }
87 :
88 : // res > 0 => Committed
89 : // res == 0 => Rejected
90 : // res < 0 => Missing
91 5260 : if (res > 0) {
92 517 : return boost::make_optional<TxCacheStatusType>(
93 517 : tx_cache_status_responses::Committed{hash});
94 4742 : } else if (res == 0) {
95 2 : return boost::make_optional<TxCacheStatusType>(
96 2 : tx_cache_status_responses::Rejected{hash});
97 : }
98 4757 : return boost::make_optional<TxCacheStatusType>(
99 4584 : tx_cache_status_responses::Missing{hash});
100 5315 : }
101 :
102 : uint32_t PostgresBlockQuery::getTopBlockHeight() {
103 721 : return block_store_.last_id();
104 : }
105 :
106 : expected::Result<BlockQuery::wBlock, std::string>
107 : PostgresBlockQuery::getTopBlock() {
108 1520 : return getBlock(block_store_.last_id())
109 1520 : .match(
110 : [](expected::Value<
111 : std::unique_ptr<shared_model::interface::Block>> &v)
112 : -> expected::Result<BlockQuery::wBlock, std::string> {
113 989 : return expected::makeValue<BlockQuery::wBlock>(
114 989 : std::move(v.value));
115 0 : },
116 : [](expected::Error<std::string> &e)
117 : -> expected::Result<BlockQuery::wBlock, std::string> {
118 531 : return expected::makeError(std::move(e.error));
119 0 : });
120 0 : }
121 :
122 : expected::Result<std::unique_ptr<shared_model::interface::Block>,
123 : std::string>
124 : PostgresBlockQuery::getBlock(
125 : shared_model::interface::types::HeightType id) const {
126 2028 : auto serialized_block = block_store_.get(id);
127 2028 : if (not serialized_block) {
128 532 : auto error = boost::format("Failed to retrieve block with id %d") % id;
129 532 : return expected::makeError(error.str());
130 532 : }
131 1496 : return converter_->deserialize(bytesToString(*serialized_block));
132 2028 : }
133 : } // namespace ametsuchi
134 : } // namespace iroha
|