BitShares-Core  7.0.2
BitShares blockchain node software and command-line wallet software
api_helper_indexes.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2018 api_helper_indexes and contributors.
3  *
4  * The MIT License
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a copy
7  * of this software and associated documentation files (the "Software"), to deal
8  * in the Software without restriction, including without limitation the rights
9  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10  * copies of the Software, and to permit persons to whom the Software is
11  * furnished to do so, subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be included in
14  * all copies or substantial portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22  * THE SOFTWARE.
23  */
24 
30 
31 namespace graphene { namespace api_helper_indexes {
32 
34 { try {
35  const call_order_object& o = static_cast<const call_order_object&>( objct );
36 
37  {
38  auto itr = in_collateral.find( o.collateral_type() );
39  if( itr == in_collateral.end() )
40  in_collateral[o.collateral_type()] = o.collateral;
41  else
42  itr->second += o.collateral;
43  }
44 
45  {
46  auto itr = backing_collateral.find( o.debt_type() );
47  if( itr == backing_collateral.end() )
48  backing_collateral[o.debt_type()] = o.collateral;
49  else
50  itr->second += o.collateral;
51  }
52 
53 } FC_CAPTURE_AND_RETHROW( (objct) ) } // GCOVR_EXCL_LINE
54 
55 void amount_in_collateral_index::object_removed( const object& objct )
56 { try {
57  const call_order_object& o = static_cast<const call_order_object&>( objct );
58 
59  {
60  auto itr = in_collateral.find( o.collateral_type() );
61  if( itr != in_collateral.end() ) // should always be true
62  itr->second -= o.collateral;
63  }
64 
65  {
66  auto itr = backing_collateral.find( o.debt_type() );
67  if( itr != backing_collateral.end() ) // should always be true
68  itr->second -= o.collateral;
69  }
70 
71 } FC_CAPTURE_AND_RETHROW( (objct) ) } // GCOVR_EXCL_LINE
72 
74 { try {
75  object_removed( objct );
76 } FC_CAPTURE_AND_RETHROW( (objct) ) } // GCOVR_EXCL_LINE
77 
79 { try {
80  object_inserted( objct );
81 } FC_CAPTURE_AND_RETHROW( (objct) ) } // GCOVR_EXCL_LINE
82 
84 { try {
85  auto itr = in_collateral.find( asst );
86  if( itr == in_collateral.end() ) return 0;
87  return itr->second;
88 } FC_CAPTURE_AND_RETHROW( (asst) ) } // GCOVR_EXCL_LINE
89 
91 { try {
92  auto itr = backing_collateral.find( asst );
93  if( itr == backing_collateral.end() ) return 0;
94  return itr->second;
95 } FC_CAPTURE_AND_RETHROW( (asst) ) } // GCOVR_EXCL_LINE
96 
98 { try {
99  const auto& o = static_cast<const liquidity_pool_object&>( objct );
100  const liquidity_pool_id_type pool_id = o.get_id();
101  asset_in_pools_map[ o.asset_a ].insert( pool_id ); // Note: [] operator will create an entry if not found
102  asset_in_pools_map[ o.asset_b ].insert( pool_id );
103 } FC_CAPTURE_AND_RETHROW( (objct) ) } // GCOVR_EXCL_LINE
104 
106 { try {
107  const auto& o = static_cast<const liquidity_pool_object&>( objct );
108  const liquidity_pool_id_type pool_id = o.get_id();
109  asset_in_pools_map[ o.asset_a ].erase( pool_id );
110  asset_in_pools_map[ o.asset_b ].erase( pool_id );
111  // Note: do not erase entries with an empty set from the map in order to avoid read/write race conditions
112 } FC_CAPTURE_AND_RETHROW( (objct) ) } // GCOVR_EXCL_LINE
113 
115 {
116  // this secondary index has no interest in the modifications, nothing to do here
117 }
118 
120 {
121  // this secondary index has no interest in the modifications, nothing to do here
122 }
123 
124 const flat_set<liquidity_pool_id_type>& asset_in_liquidity_pools_index::get_liquidity_pools_by_asset(
125  const asset_id_type& a )const
126 {
127  auto itr = asset_in_pools_map.find( a );
128  if( itr != asset_in_pools_map.end() )
129  return itr->second;
130  return empty_set;
131 }
132 
133 namespace detail
134 {
135 
137 {
138  public:
140  : _self( _plugin )
141  { }
142 
144  {
145  return _self.database();
146  }
147 
148  private:
149  api_helper_indexes& _self;
150 };
151 
152 } // end namespace detail
153 
155  plugin(app),
156  my( std::make_unique<detail::api_helper_indexes_impl>(*this) )
157 {
158  // Nothing else to do
159 }
160 
161 api_helper_indexes::~api_helper_indexes() = default;
162 
163 std::string api_helper_indexes::plugin_name()const
164 {
165  return "api_helper_indexes";
166 }
167 std::string api_helper_indexes::plugin_description()const
168 {
169  return "Provides some helper indexes used by various API calls";
170 }
171 
172 void api_helper_indexes::plugin_set_program_options(
173  boost::program_options::options_description& cli,
174  boost::program_options::options_description& cfg
175  )
176 {
177 }
178 
179 void api_helper_indexes::plugin_initialize(const boost::program_options::variables_map& options)
180 {
181 }
182 
183 void api_helper_indexes::plugin_startup()
184 {
185  ilog("api_helper_indexes: plugin_startup() begin");
186  amount_in_collateral_idx = database().add_secondary_index< primary_index<call_order_index>,
188  for( const auto& call : database().get_index_type<call_order_index>().indices() )
189  amount_in_collateral_idx->object_inserted( call );
190 
192  for( const auto& account : database().get_index_type< account_index >().indices() )
193  account_members.object_inserted( account );
194 
196  for( const auto& proposal : database().get_index_type< proposal_index >().indices() )
197  approvals.object_inserted( proposal );
198 
199  asset_in_liquidity_pools_idx = database().add_secondary_index< primary_index<liquidity_pool_index>,
201  for( const auto& pool : database().get_index_type<liquidity_pool_index>().indices() )
202  asset_in_liquidity_pools_idx->object_inserted( pool );
203 
206  refresh_next_ids();
207  // connect with no group specified to process after the ones with a group specified
208  database().applied_block.connect( [this]( const chain::signed_block& )
209  {
210  refresh_next_ids();
211  _next_ids_map_initialized = true;
212  });
213 }
214 
215 void api_helper_indexes::refresh_next_ids()
216 {
217  const auto& db = database();
218  if( _next_ids_map_initialized )
219  {
220  for( auto& item : next_object_ids_idx->_next_ids )
221  {
222  item.second = db.get_index( item.first.first, item.first.second ).get_next_id();
223  }
224  return;
225  }
226 
227  // Assuming that all indexes have been created when processing the first block,
228  // for better performance, only do this twice, one on plugin startup, the other on the first block.
229  size_t count = 0;
230  size_t failed_count = 0;
231  for( uint8_t space = 0; space < chain::database::_index_size; ++space )
232  {
233  for( uint8_t type = 0; type < chain::database::_index_size; ++type )
234  {
235  try
236  {
237  const auto& idx = db.get_index( space, type );
238  next_object_ids_idx->_next_ids[ std::make_pair( space, type ) ] = idx.get_next_id();
239  ++count;
240  }
241  catch( const fc::exception& )
242  {
243  ++failed_count;
244  }
245  }
246  }
247  dlog( "${count} indexes detected, ${failed_count} not found", ("count",count)("failed_count",failed_count) );
248 }
249 
250 object_id_type next_object_ids_index::get_next_id( uint8_t space_id, uint8_t type_id ) const
251 { try {
252  return _next_ids.at( std::make_pair( space_id, type_id ) );
253 } FC_CAPTURE_AND_RETHROW( (space_id)(type_id) ) } // GCOVR_EXCL_LINE
254 
255 } }
graphene::db::object_database::add_secondary_index
SecondaryIndexType * add_secondary_index(Args... args)
Definition: object_database.hpp:159
FC_CAPTURE_AND_RETHROW
#define FC_CAPTURE_AND_RETHROW(...)
Definition: exception.hpp:479
liquidity_pool_object.hpp
graphene::api_helper_indexes::next_object_ids_index::get_next_id
object_id_type get_next_id(uint8_t space_id, uint8_t type_id) const
Definition: api_helper_indexes.cpp:250
graphene::chain::database
tracks the blockchain state in an extensible manner
Definition: database.hpp:70
fc::exception
Used to generate a useful error report when an exception is thrown.
Definition: exception.hpp:56
graphene::db::primary_index
Wraps a derived index to intercept calls to create, modify, and remove so that callbacks may be fired...
Definition: index.hpp:312
graphene::app::plugin::database
chain::database & database()
Definition: plugin.hpp:115
graphene::chain::call_order_object::collateral_type
asset_id_type collateral_type() const
Definition: market_object.hpp:147
graphene::chain::account_member_index::object_inserted
virtual void object_inserted(const object &obj) override
Definition: account_object.cpp:137
chain_property_object.hpp
graphene::api_helper_indexes::amount_in_collateral_index::get_amount_in_collateral
share_type get_amount_in_collateral(const asset_id_type &asset) const
Definition: api_helper_indexes.cpp:83
proposal_object.hpp
graphene::chain::call_order_object::collateral
share_type collateral
call_price.base.asset_id, access via get_collateral
Definition: market_object.hpp:151
graphene::api_helper_indexes::amount_in_collateral_index
This secondary index tracks how much of each asset is locked up as collateral for MPAs,...
Definition: api_helper_indexes.hpp:38
graphene::chain::database::applied_block
fc::signal< void(const signed_block &)> applied_block
Definition: database.hpp:624
graphene::api_helper_indexes::asset_in_liquidity_pools_index::object_modified
void object_modified(const object &after) override
Definition: api_helper_indexes.cpp:119
graphene::chain::call_order_object::debt_type
asset_id_type debt_type() const
Definition: market_object.hpp:146
graphene::chain::account_member_index
This secondary index will allow a reverse lookup of all accounts that a particular key or account is ...
Definition: account_object.hpp:330
graphene::app::application
Definition: application.hpp:91
graphene::api_helper_indexes::detail::api_helper_indexes_impl::api_helper_indexes_impl
api_helper_indexes_impl(api_helper_indexes &_plugin)
Definition: api_helper_indexes.cpp:139
graphene::api_helper_indexes::amount_in_collateral_index::get_backing_collateral
share_type get_backing_collateral(const asset_id_type &asset) const
Definition: api_helper_indexes.cpp:90
graphene::db::object_database::_index_size
static constexpr uint8_t _index_size
Definition: object_database.hpp:45
ilog
#define ilog(FORMAT,...)
Definition: logger.hpp:117
dlog
#define dlog(FORMAT,...)
Definition: logger.hpp:100
graphene::api_helper_indexes::detail::api_helper_indexes_impl::database
graphene::chain::database & database()
Definition: api_helper_indexes.cpp:143
graphene::api_helper_indexes::api_helper_indexes
Definition: api_helper_indexes.hpp:94
graphene::chain::required_approval_index
tracks all of the proposal objects that requrie approval of an individual account.
Definition: proposal_object.hpp:68
api_helper_indexes.hpp
graphene::api_helper_indexes::next_object_ids_index
This secondary index tracks the next ID of all object types.
Definition: api_helper_indexes.hpp:79
graphene::chain::required_approval_index::object_inserted
virtual void object_inserted(const object &obj) override
Definition: proposal_object.cpp:60
graphene::api_helper_indexes::amount_in_collateral_index::object_removed
void object_removed(const object &obj) override
Definition: api_helper_indexes.cpp:55
graphene::chain::liquidity_pool_object
A liquidity pool.
Definition: liquidity_pool_object.hpp:44
graphene::db::object_id_type
Definition: object_id.hpp:30
graphene::api_helper_indexes::asset_in_liquidity_pools_index::about_to_modify
void about_to_modify(const object &before) override
Definition: api_helper_indexes.cpp:114
std
Definition: zeroed_array.hpp:76
graphene::api_helper_indexes::detail::api_helper_indexes_impl
Definition: api_helper_indexes.cpp:136
graphene::chain::call_order_object
tracks debt and call price information
Definition: market_object.hpp:140
graphene::db::generic_index
Definition: generic_index.hpp:43
graphene::api_helper_indexes::asset_in_liquidity_pools_index::object_inserted
void object_inserted(const object &obj) override
Definition: api_helper_indexes.cpp:97
graphene::api_helper_indexes::asset_in_liquidity_pools_index
This secondary index maintains a map to make it easier to find liquidity pools by any asset in the po...
Definition: api_helper_indexes.hpp:59
graphene::db::abstract_object::get_id
object_id< SpaceID, TypeID > get_id() const
Definition: object.hpp:113
graphene::api_helper_indexes::asset_in_liquidity_pools_index::get_liquidity_pools_by_asset
const flat_set< liquidity_pool_id_type > & get_liquidity_pools_by_asset(const asset_id_type &a) const
Definition: api_helper_indexes.cpp:124
graphene::api_helper_indexes::amount_in_collateral_index::object_modified
void object_modified(const object &after) override
Definition: api_helper_indexes.cpp:78
graphene::api_helper_indexes::asset_in_liquidity_pools_index::object_removed
void object_removed(const object &obj) override
Definition: api_helper_indexes.cpp:105
market_object.hpp
graphene::protocol::signed_block
Definition: block.hpp:64
graphene::db::object_database::get_index_type
const IndexType & get_index_type() const
Definition: object_database.hpp:77
graphene::api_helper_indexes::amount_in_collateral_index::about_to_modify
void about_to_modify(const object &before) override
Definition: api_helper_indexes.cpp:73
graphene
Definition: api.cpp:48
graphene::api_helper_indexes::amount_in_collateral_index::object_inserted
void object_inserted(const object &obj) override
Definition: api_helper_indexes.cpp:33
fc::safe
Definition: safe.hpp:26