LCOV - code coverage report
Current view: top level - irohad/ametsuchi/impl - postgres_block_index.cpp (source / functions) Hit Total Coverage
Test: coverage_cleared.info Lines: 60 65 92.3 %
Date: 2018-12-05 17:11:35 Functions: 33 33 100.0 %

          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_index.hpp"
       7             : 
       8             : #include <boost/range/adaptor/indexed.hpp>
       9             : 
      10             : #include "ametsuchi/tx_cache_response.hpp"
      11             : #include "common/visitor.hpp"
      12             : #include "interfaces/commands/command_variant.hpp"
      13             : #include "interfaces/commands/transfer_asset.hpp"
      14             : #include "interfaces/iroha_internal/block.hpp"
      15             : 
      16             : namespace {
      17             :   // Return transfer asset if command contains it
      18             :   boost::optional<const shared_model::interface::TransferAsset &>
      19             :   getTransferAsset(const shared_model::interface::Command &cmd) noexcept {
      20             :     using ReturnType =
      21             :         boost::optional<const shared_model::interface::TransferAsset &>;
      22        5904 :     return iroha::visit_in_place(
      23        5904 :         cmd.get(),
      24             :         [](const shared_model::interface::TransferAsset &c) {
      25          83 :           return ReturnType(c);
      26             :         },
      27             :         [](const auto &) -> ReturnType { return boost::none; });
      28             :   }
      29             : 
      30             :   // make index tx hash -> block where hash is stored
      31             :   std::string makeHashIndex(
      32             :       const shared_model::interface::types::HashType &hash,
      33             :       shared_model::interface::types::HeightType height) {
      34        1316 :     boost::format base(
      35             :         "INSERT INTO height_by_hash(hash, height) VALUES ('%s', "
      36             :         "'%s');");
      37        1316 :     return (base % hash.hex() % height).str();
      38        1316 :   }
      39             : 
      40             :   std::string makeCommittedTxHashIndex(
      41             :       const shared_model::interface::types::HashType &rejected_tx_hash) {
      42        1316 :     boost::format base(
      43             :         "INSERT INTO tx_status_by_hash(hash, status) VALUES ('%s', "
      44             :         "TRUE);");
      45        1316 :     return (base % rejected_tx_hash.hex()).str();
      46        1316 :   }
      47             : 
      48             :   std::string makeRejectedTxHashIndex(
      49             :       const shared_model::interface::types::HashType &rejected_tx_hash) {
      50          72 :     boost::format base(
      51             :         "INSERT INTO tx_status_by_hash(hash, status) VALUES ('%s', "
      52             :         "FALSE);");
      53          72 :     return (base % rejected_tx_hash.hex()).str();
      54          72 :   }
      55             : 
      56             :   // make index account_id:height -> list of tx indexes
      57             :   // (where tx is placed in the block)
      58             :   std::string makeCreatorHeightIndex(
      59             :       const shared_model::interface::types::AccountIdType creator,
      60             :       shared_model::interface::types::HeightType height,
      61             :       size_t tx_index) {
      62        1316 :     boost::format base(
      63             :         "INSERT INTO index_by_creator_height(creator_id, height, index) VALUES "
      64             :         "('%s', '%s', '%s');");
      65        1316 :     return (base % creator % height % tx_index).str();
      66        1316 :   }
      67             : 
      68             :   // Make index account_id -> list of blocks where his txs exist
      69             :   std::string makeAccountHeightIndex(
      70             :       const shared_model::interface::types::AccountIdType &account_id,
      71             :       shared_model::interface::types::HeightType height) {
      72        1482 :     boost::format base(
      73             :         "INSERT INTO height_by_account_set(account_id, "
      74             :         "height) VALUES "
      75             :         "('%s', '%s');");
      76        1482 :     return (base % account_id % height).str();
      77        1482 :   }
      78             : 
      79             :   // Collect all assets belonging to creator, sender, and receiver
      80             :   // to make account_id:height:asset_id -> list of tx indexes
      81             :   // for transfer asset in command
      82             :   std::string makeAccountAssetIndex(
      83             :       const shared_model::interface::types::AccountIdType &account_id,
      84             :       shared_model::interface::types::HeightType height,
      85             :       size_t index,
      86             :       const shared_model::interface::Transaction::CommandsType &commands) {
      87        1316 :     return std::accumulate(
      88        1316 :         commands.begin(),
      89        1316 :         commands.end(),
      90        1316 :         std::string{},
      91             :         [&](auto query, const auto &cmd) {
      92             :           auto transfer = getTransferAsset(cmd);
      93        5904 :           if (not transfer) {
      94        5821 :             return query;
      95             :           }
      96          83 :           const auto &src_id = transfer.value().srcAccountId();
      97          83 :           const auto &dest_id = transfer.value().destAccountId();
      98             : 
      99          83 :           query += makeAccountHeightIndex(src_id, height);
     100          83 :           query += makeAccountHeightIndex(dest_id, height);
     101             : 
     102             :           const auto ids = {account_id, src_id, dest_id};
     103          83 :           const auto &asset_id = transfer.value().assetId();
     104             :           // flat map accounts to unindexed keys
     105         332 :           for (const auto &id : ids) {
     106         249 :             boost::format base(
     107             :                 "INSERT INTO index_by_id_height_asset(id, "
     108             :                 "height, asset_id, "
     109             :                 "index) "
     110             :                 "VALUES ('%s', '%s', '%s', '%s');");
     111         249 :             query += (base % id % height % asset_id % index).str();
     112             :           }
     113          83 :           return query;
     114        5904 :         });
     115           0 :   }
     116             : }  // namespace
     117             : 
     118             : namespace iroha {
     119             :   namespace ametsuchi {
     120             :     PostgresBlockIndex::PostgresBlockIndex(soci::session &sql)
     121        1268 :         : sql_(sql), log_(logger::log("PostgresBlockIndex")) {}
     122             : 
     123             :     void PostgresBlockIndex::index(
     124             :         const shared_model::interface::Block &block) {
     125        1290 :       auto height = block.height();
     126        1290 :       auto indexed_txs = block.transactions() | boost::adaptors::indexed(0);
     127        1290 :       auto rejected_txs_hashes = block.rejected_transactions_hashes();
     128        1290 :       std::string tx_index_query = std::accumulate(
     129        1290 :           indexed_txs.begin(),
     130        1290 :           indexed_txs.end(),
     131        1290 :           std::string{},
     132             :           [height](auto query, const auto &tx) {
     133        1316 :             const auto &creator_id = tx.value().creatorAccountId();
     134        1316 :             const auto index = tx.index();
     135             : 
     136        1316 :             query += makeAccountHeightIndex(creator_id, height);
     137        1316 :             query += makeAccountAssetIndex(
     138        1316 :                 creator_id, height, index, tx.value().commands());
     139        1316 :             query += makeHashIndex(tx.value().hash(), height);
     140        1316 :             query += makeCommittedTxHashIndex(tx.value().hash());
     141        1316 :             query += makeCreatorHeightIndex(creator_id, height, index);
     142        1316 :             return query;
     143           0 :           });
     144             : 
     145             :       std::string rejected_tx_index_query =
     146        1290 :           std::accumulate(rejected_txs_hashes.begin(),
     147        1290 :                           rejected_txs_hashes.end(),
     148        1290 :                           std::string{},
     149             :                           [](auto query, const auto &rejected_tx_hash) {
     150          72 :                             query += makeRejectedTxHashIndex(rejected_tx_hash);
     151          72 :                             return query;
     152           0 :                           });
     153             : 
     154        1290 :       auto index_query = tx_index_query + rejected_tx_index_query;
     155             :       try {
     156        1290 :         sql_ << index_query;
     157        1290 :       } catch (const std::exception &e) {
     158           0 :         log_->error(e.what());
     159           0 :       }
     160        1290 :     }
     161             :   }  // namespace ametsuchi
     162             : }  // namespace iroha

Generated by: LCOV version 1.13