Line data Source code
1 : /**
2 : * Copyright Soramitsu Co., Ltd. 2017 All Rights Reserved.
3 : * http://soramitsu.co.jp
4 : *
5 : * Licensed under the Apache License, Version 2.0 (the "License");
6 : * you may not use this file except in compliance with the License.
7 : * You may obtain a copy of the License at
8 : *
9 : * http://www.apache.org/licenses/LICENSE-2.0
10 : *
11 : * Unless required by applicable law or agreed to in writing, software
12 : * distributed under the License is distributed on an "AS IS" BASIS,
13 : * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 : * See the License for the specific language governing permissions and
15 : * limitations under the License.
16 : */
17 :
18 : #include "network/impl/block_loader_service.hpp"
19 : #include "backend/protobuf/block.hpp"
20 : #include "common/bind.hpp"
21 :
22 : using namespace iroha;
23 : using namespace iroha::ametsuchi;
24 : using namespace iroha::network;
25 :
26 : BlockLoaderService::BlockLoaderService(
27 : std::shared_ptr<BlockQueryFactory> block_query_factory,
28 : std::shared_ptr<iroha::consensus::ConsensusResultCache>
29 : consensus_result_cache)
30 252 : : block_query_factory_(std::move(block_query_factory)),
31 252 : consensus_result_cache_(std::move(consensus_result_cache)),
32 252 : log_(logger::log("BlockLoaderService")) {}
33 :
34 : grpc::Status BlockLoaderService::retrieveBlocks(
35 : ::grpc::ServerContext *context,
36 : const proto::BlocksRequest *request,
37 : ::grpc::ServerWriter<::iroha::protocol::Block> *writer) {
38 3 : auto blocks = block_query_factory_->createBlockQuery() |
39 : [height = request->height()](const auto &block_query) {
40 3 : return block_query->getBlocksFrom(height);
41 : };
42 : std::for_each(blocks.begin(), blocks.end(), [&writer](const auto &block) {
43 3 : writer->Write(std::dynamic_pointer_cast<shared_model::proto::Block>(block)
44 3 : ->getTransport());
45 3 : });
46 3 : return grpc::Status::OK;
47 3 : }
48 :
49 : grpc::Status BlockLoaderService::retrieveBlock(
50 : ::grpc::ServerContext *context,
51 : const proto::BlockRequest *request,
52 : protocol::Block *response) {
53 4 : const auto hash = shared_model::crypto::Hash(request->hash());
54 4 : if (hash.size() == 0) {
55 0 : log_->error("Bad hash in request");
56 0 : return grpc::Status(grpc::StatusCode::INVALID_ARGUMENT,
57 0 : "Bad hash provided");
58 : }
59 :
60 : // try to fetch block from the consensus cache
61 4 : auto block = consensus_result_cache_->get();
62 4 : if (block) {
63 2 : if (block->hash() == hash) {
64 1 : *response = std::static_pointer_cast<shared_model::proto::Block>(block)
65 1 : ->getTransport();
66 1 : return grpc::Status::OK;
67 : } else {
68 1 : log_->info(
69 : "Requested to retrieve a block, but cache contains another block: "
70 : "requested {}, in cache {}",
71 1 : hash.hex(),
72 1 : block->hash().hex());
73 : }
74 1 : } else {
75 2 : log_->info(
76 : "Tried to retrieve a block from an empty cache: requested block hash "
77 : "{}",
78 2 : hash.hex());
79 : }
80 :
81 : // cache missed: notify and try to fetch the block from block storage itself
82 : auto blocks = block_query_factory_->createBlockQuery() |
83 : // TODO [IR-1757] Akvinikym 12.10.18: use block height to get one block
84 : // instead of the whole chain
85 : [](const auto &block_query) {
86 3 : return boost::make_optional(block_query->getBlocksFrom(1));
87 0 : };
88 3 : if (not blocks) {
89 0 : log_->error("Could not create block query to retrieve block from storage");
90 0 : return grpc::Status(grpc::StatusCode::INTERNAL, "internal error happened");
91 : }
92 :
93 3 : auto found_block = std::find_if(
94 : std::begin(*blocks), std::end(*blocks), [&hash](const auto &block) {
95 2 : return block->hash() == hash;
96 : });
97 3 : if (found_block == std::end(*blocks)) {
98 1 : log_->error("Could not retrieve a block from block storage: requested {}",
99 1 : hash.hex());
100 1 : return grpc::Status(grpc::StatusCode::NOT_FOUND, "Block not found");
101 : }
102 :
103 2 : *response = std::static_pointer_cast<shared_model::proto::Block>(*found_block)
104 2 : ->getTransport();
105 2 : return grpc::Status::OK;
106 4 : }
|