#47 Fix crash, added history lenght limits, added init testing

This commit is contained in:
Daniel Larimer 2015-06-24 14:01:37 -04:00
parent af812a7b51
commit aaf31d840f
3 changed files with 57 additions and 8 deletions

View file

@ -117,6 +117,7 @@ class market_history_plugin : public graphene::app::plugin
const boost::program_options::variables_map& options) override; const boost::program_options::variables_map& options) override;
virtual void plugin_startup() override; virtual void plugin_startup() override;
uint32_t max_history()const;
const flat_set<uint32_t>& tracked_buckets()const; const flat_set<uint32_t>& tracked_buckets()const;
private: private:

View file

@ -53,6 +53,7 @@ class market_history_plugin_impl
market_history_plugin& _self; market_history_plugin& _self;
flat_set<uint32_t> _tracked_buckets; flat_set<uint32_t> _tracked_buckets;
uint32_t _maximum_history_per_bucket_size = 1000;
}; };
@ -76,17 +77,23 @@ struct operation_process_fill_order
auto& db = _plugin.database(); auto& db = _plugin.database();
const auto& bucket_idx = db.get_index_type<bucket_index>(); const auto& bucket_idx = db.get_index_type<bucket_index>();
auto max_history = _plugin.max_history();
for( auto bucket : buckets ) for( auto bucket : buckets )
{ {
auto cutoff = (fc::time_point() + fc::seconds( bucket * max_history));
bucket_key key; bucket_key key;
key.base = o.pays.asset_id; key.base = o.pays.asset_id;
key.quote = o.receives.asset_id; key.quote = o.receives.asset_id;
price trade_price = o.pays / o.receives;
/** for every matched order there are two fill order operations created, one for
* each side. We can filter the duplicates by only considering the fill operations where
* the base > quote
*/
if( key.base > key.quote ) if( key.base > key.quote )
{ continue;
std::swap( key.base,key.quote );
trade_price = ~trade_price; price trade_price = o.pays / o.receives;
}
key.seconds = bucket; key.seconds = bucket;
key.open = fc::time_point() + fc::seconds((_now.sec_since_epoch() / key.seconds) * key.seconds); key.open = fc::time_point() + fc::seconds((_now.sec_since_epoch() / key.seconds) * key.seconds);
@ -127,6 +134,23 @@ struct operation_process_fill_order
} }
}); });
} }
if( max_history != 0 )
{
key.open = fc::time_point_sec();
auto itr = by_key_idx.lower_bound( key );
while( itr != by_key_idx.end() &&
itr->key.base == key.base &&
itr->key.quote == key.quote &&
itr->key.seconds == bucket &&
itr->key.open < cutoff )
{
auto old_itr = itr;
++itr;
db.remove( *old_itr );
}
}
} }
} }
}; };
@ -136,6 +160,9 @@ market_history_plugin_impl::~market_history_plugin_impl()
void market_history_plugin_impl::update_market_histories( const signed_block& b ) void market_history_plugin_impl::update_market_histories( const signed_block& b )
{ {
if( _maximum_history_per_bucket_size == 0 ) return;
if( _tracked_buckets.size() == 0 ) return;
graphene::chain::database& db = database(); graphene::chain::database& db = database();
const vector<operation_history_object>& hist = db.get_applied_operations(); const vector<operation_history_object>& hist = db.get_applied_operations();
for( auto op : hist ) for( auto op : hist )
@ -169,18 +196,23 @@ void market_history_plugin::plugin_set_program_options(
) )
{ {
cli.add_options() cli.add_options()
("bucket-size", boost::program_options::value<std::vector<uint32_t>>()->composing()->multitoken(), "Bucket size in seconds to track history for (may specify multiple times)") ("bucket-size", boost::program_options::value<std::vector<uint32_t>>()->composing()->multitoken(),
"Track market history by grouping orders into buckets of equal size measured in seconds, may specify more than one bucket size")
("history-per-size", boost::program_options::value<uint32_t>()->default_value(1000),
"How far back in time to track history for each bucket size, measured in the number of buckets (default: 1000)")
; ;
cfg.add(cli); cfg.add(cli);
} }
void market_history_plugin::plugin_initialize(const boost::program_options::variables_map& options) void market_history_plugin::plugin_initialize(const boost::program_options::variables_map& options)
{ { try {
database().applied_block.connect( [&]( const signed_block& b){ my->update_market_histories(b); } ); database().applied_block.connect( [&]( const signed_block& b){ my->update_market_histories(b); } );
database().add_index< primary_index< bucket_index > >(); database().add_index< primary_index< bucket_index > >();
LOAD_VALUE_SET(options, "bucket-size", my->_tracked_buckets, uint32_t); LOAD_VALUE_SET(options, "bucket-size", my->_tracked_buckets, uint32_t);
} if( options.count( "history-per-size" ) )
my->_maximum_history_per_bucket_size = options["history-per-size"].as<uint32_t>();
} FC_CAPTURE_AND_RETHROW() }
void market_history_plugin::plugin_startup() void market_history_plugin::plugin_startup()
{ {
@ -191,4 +223,9 @@ const flat_set<uint32_t>& market_history_plugin::tracked_buckets() const
return my->_tracked_buckets; return my->_tracked_buckets;
} }
uint32_t market_history_plugin::max_history()const
{
return my->_maximum_history_per_bucket_size;
}
} } } }

View file

@ -19,6 +19,7 @@
#include <boost/program_options.hpp> #include <boost/program_options.hpp>
#include <graphene/account_history/account_history_plugin.hpp> #include <graphene/account_history/account_history_plugin.hpp>
#include <graphene/market_history/market_history_plugin.hpp>
#include <graphene/db/simple_index.hpp> #include <graphene/db/simple_index.hpp>
@ -46,13 +47,17 @@ using std::cerr;
database_fixture::database_fixture() database_fixture::database_fixture()
: app(), db( *app.chain_database() ) : app(), db( *app.chain_database() )
{ {
try {
auto ahplugin = app.register_plugin<graphene::account_history::account_history_plugin>(); auto ahplugin = app.register_plugin<graphene::account_history::account_history_plugin>();
auto mhplugin = app.register_plugin<graphene::market_history::market_history_plugin>();
boost::program_options::variables_map options; boost::program_options::variables_map options;
// app.initialize(); // app.initialize();
ahplugin->plugin_set_app(&app); ahplugin->plugin_set_app(&app);
ahplugin->plugin_initialize(options); ahplugin->plugin_initialize(options);
mhplugin->plugin_set_app(&app);
mhplugin->plugin_initialize(options);
secret_hash_type::encoder enc; secret_hash_type::encoder enc;
fc::raw::pack(enc, delegate_priv_key); fc::raw::pack(enc, delegate_priv_key);
@ -68,11 +73,17 @@ database_fixture::database_fixture()
fc::reflector<fee_schedule_type>::visit(fee_schedule_type::fee_set_visitor{genesis_state.initial_parameters.current_fees, 0}); fc::reflector<fee_schedule_type>::visit(fee_schedule_type::fee_set_visitor{genesis_state.initial_parameters.current_fees, 0});
db.init_genesis(genesis_state); db.init_genesis(genesis_state);
ahplugin->plugin_startup(); ahplugin->plugin_startup();
mhplugin->plugin_startup();
generate_block(); generate_block();
genesis_key(db); // attempt to deref genesis_key(db); // attempt to deref
trx.set_expiration(db.head_block_time() + fc::minutes(1)); trx.set_expiration(db.head_block_time() + fc::minutes(1));
} catch ( const fc::exception& e )
{
edump( (e.to_detail_string()) );
throw;
}
return; return;
} }