BitShares-Core  6.1.0
BitShares blockchain implementation and command-line interface 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) ) }
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) ) }
72 
74 { try {
75  object_removed( objct );
76 } FC_CAPTURE_AND_RETHROW( (objct) ) }
77 
79 { try {
80  object_inserted( objct );
81 } FC_CAPTURE_AND_RETHROW( (objct) ) }
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) ) }
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) ) }
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) ) }
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) ) }
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 
162 
164 {
165  return "api_helper_indexes";
166 }
168 {
169  return "Provides some helper indexes used by various API calls";
170 }
171 
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 
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) ) }
254 
255 } }
tracks all of the proposal objects that requrie approval of an individual account.
This secondary index tracks the next ID of all object types.
Wraps a derived index to intercept calls to create, modify, and remove so that callbacks may be fired...
Definition: index.hpp:312
void plugin_startup() override
Begin normal runtime operations.
SecondaryIndexType * add_secondary_index(Args... args)
fc::signal< void(const signed_block &)> applied_block
Definition: database.hpp:606
share_type get_backing_collateral(const asset_id_type &asset) const
tracks the blockchain state in an extensible manner
Definition: database.hpp:70
const IndexType & get_index_type() const
Definition: api.cpp:48
tracks debt and call price information
Used to generate a useful error report when an exception is thrown.At each level in the stack where t...
Definition: exception.hpp:56
std::string plugin_name() const override
Get the name of the plugin.
object_id_type get_next_id(uint8_t space_id, uint8_t type_id) const
This secondary index maintains a map to make it easier to find liquidity pools by any asset in the po...
api_helper_indexes(graphene::app::application &app)
asset_id_type collateral_type() const
static constexpr uint8_t _index_size
object_id< SpaceID, TypeID > get_id() const
Definition: object.hpp:113
chain::database & database()
Definition: plugin.hpp:115
This secondary index tracks how much of each asset is locked up as collateral for MPAs...
#define ilog(FORMAT,...)
Definition: logger.hpp:117
This secondary index will allow a reverse lookup of all accounts that a particular key or account is ...
void plugin_set_program_options(boost::program_options::options_description &cli, boost::program_options::options_description &cfg) override
Fill in command line parameters used by the plugin.
#define FC_CAPTURE_AND_RETHROW(...)
Definition: exception.hpp:479
std::string plugin_description() const override
Get the description of the plugin.
void plugin_initialize(const boost::program_options::variables_map &options) override
Perform early startup routines and register plugin indexes, callbacks, etc.
virtual void object_inserted(const object &obj) override
share_type get_amount_in_collateral(const asset_id_type &asset) const
#define dlog(FORMAT,...)
Definition: logger.hpp:100
const flat_set< liquidity_pool_id_type > & get_liquidity_pools_by_asset(const asset_id_type &a) const
share_type collateral
call_price.base.asset_id, access via get_collateral
virtual void object_inserted(const object &obj) override