From 0313558eca5bbe58bd6ee34dc98bfde1d810c9c8 Mon Sep 17 00:00:00 2001 From: Matias Romeo Date: Sat, 26 Aug 2017 03:59:18 -0300 Subject: [PATCH] Implement get_table_rows for every table type #193 --- plugins/chain_api_plugin/chain_api_plugin.cpp | 3 +- plugins/chain_plugin/chain_plugin.cpp | 99 +++------------ .../include/eos/chain_plugin/chain_plugin.hpp | 119 +++++++++++++----- 3 files changed, 104 insertions(+), 117 deletions(-) diff --git a/plugins/chain_api_plugin/chain_api_plugin.cpp b/plugins/chain_api_plugin/chain_api_plugin.cpp index c88a8cd42..8434cd4e6 100644 --- a/plugins/chain_api_plugin/chain_api_plugin.cpp +++ b/plugins/chain_api_plugin/chain_api_plugin.cpp @@ -51,8 +51,7 @@ void chain_api_plugin::plugin_startup() { CHAIN_RO_CALL(get_info), CHAIN_RO_CALL(get_block), CHAIN_RO_CALL(get_account), - CHAIN_RO_CALL(get_table_rows_i64), - CHAIN_RO_CALL(get_table_rows_i128i128_primary), + CHAIN_RO_CALL(get_table_rows), CHAIN_RO_CALL(abi_json_to_bin), CHAIN_RO_CALL(abi_bin_to_json), CHAIN_RW_CALL(push_block), diff --git a/plugins/chain_plugin/chain_plugin.cpp b/plugins/chain_plugin/chain_plugin.cpp index 637129cd5..99702c6ec 100644 --- a/plugins/chain_plugin/chain_plugin.cpp +++ b/plugins/chain_plugin/chain_plugin.cpp @@ -11,7 +11,6 @@ #include #include #include -#include #include #include @@ -26,6 +25,8 @@ using chain::block_log; using chain::chain_id_type; using chain::account_object; using chain::key_value_object; +using chain::key128x128_value_object; +using chain::key64x64x64_value_object; using chain::by_name; using chain::by_scope_primary; using chain::uint128_t; @@ -223,87 +224,23 @@ read_only::get_info_results read_only::get_info(const read_only::get_info_params }; } -read_only::get_table_rows_i64_result read_only::get_table_rows_i64( const read_only::get_table_rows_i64_params& p )const { - read_only::get_table_rows_i64_result result; - const auto& d = db.get_database(); - const auto& code_account = d.get( p.code ); - - types::AbiSerializer abis; - if( code_account.abi.size() > 4 ) { /// 4 == packsize of empty Abi - eos::types::Abi abi; - fc::datastream ds( code_account.abi.data(), code_account.abi.size() ); - fc::raw::unpack( ds, abi ); - abis.setAbi( abi ); - } - - const auto& idx = d.get_index(); - auto lower = idx.lower_bound( boost::make_tuple( p.scope, p.code, p.table, p.lower_bound ) ); - auto upper = idx.upper_bound( boost::make_tuple( p.scope, p.code, p.table, p.upper_bound ) ); - - vector data; - - auto start = fc::time_point::now(); - auto end = fc::time_point::now() + fc::microseconds( 1000*10 ); /// 10ms max time - - int count = 0; - auto itr = lower; - for( itr = lower; itr != upper; ++itr ) { - data.resize( sizeof(uint64_t) + itr->value.size() ); - memcpy( data.data(), &itr->primary_key, sizeof(itr->primary_key) ); - memcpy( data.data()+sizeof(uint64_t), itr->value.data(), itr->value.size() ); - - if( p.json ) - result.rows.emplace_back( abis.binaryToVariant( abis.getTableType(p.table), data ) ); - else - result.rows.emplace_back( fc::variant(data) ); - if( ++count == p.limit || fc::time_point::now() > end ) - break; +read_only::get_table_rows_result read_only::get_table_rows( const read_only::get_table_rows_params& p )const { + if( p.table_type == KEYi64 ) { + return get_table_rows_ex(p); + } else if( p.table_type == KEYi128i128 ) { + if( p.table_key == PRIMARY ) + return get_table_rows_ex(p); + if( p.table_key == SECONDARY ) + return get_table_rows_ex(p); + } else if(p.table_type == KEYi64i64i64 ) { + if( p.table_key == PRIMARY ) + return get_table_rows_ex(p); + if( p.table_key == SECONDARY ) + return get_table_rows_ex(p); + if( p.table_key == TERTIARY ) + return get_table_rows_ex(p); } - if( itr != upper ) - result.more = true; - return result; -} - -read_only::get_table_rows_i128i128_primary_result read_only::get_table_rows_i128i128_primary( const read_only::get_table_rows_i128i128_primary_params& p )const { - read_only::get_table_rows_i128i128_primary_result result; - const auto& d = db.get_database(); - const auto& code_account = d.get( p.code ); - - types::AbiSerializer abis; - if( code_account.abi.size() > 4 ) { /// 4 == packsize of empty Abi - eos::types::Abi abi; - fc::datastream ds( code_account.abi.data(), code_account.abi.size() ); - fc::raw::unpack( ds, abi ); - abis.setAbi( abi ); - } - - const auto& idx = d.get_index(); - auto lower = idx.lower_bound( boost::make_tuple( p.scope, p.code, p.table, p.lower_bound ) ); - auto upper = idx.upper_bound( boost::make_tuple( p.scope, p.code, p.table, p.upper_bound ) ); - - vector data; - - auto start = fc::time_point::now(); - auto end = fc::time_point::now() + fc::microseconds( 1000*10 ); /// 10ms max time - - int count = 0; - auto itr = lower; - for( itr = lower; itr != upper; ++itr ) { - data.resize( sizeof(uint128_t)*2 + itr->value.size() ); - memcpy( data.data(), &itr->primary_key, sizeof(itr->primary_key) ); - memcpy( data.data()+sizeof(uint128_t), &itr->secondary_key, sizeof(itr->secondary_key) ); - memcpy( data.data()+sizeof(uint128_t)*2, itr->value.data(), itr->value.size() ); - - if( p.json ) - result.rows.emplace_back( abis.binaryToVariant( abis.getTableType(p.table), data ) ); - else - result.rows.emplace_back( fc::variant(data) ); - if( ++count == p.limit || fc::time_point::now() > end ) - break; - } - if( itr != upper ) - result.more = true; - return result; + FC_ASSERT( false, "invalid table type/key ${type}/${key}", ("type",p.table_type)("key",p.table_key)); } read_only::get_block_results read_only::get_block(const read_only::get_block_params& params) const { diff --git a/plugins/chain_plugin/include/eos/chain_plugin/chain_plugin.hpp b/plugins/chain_plugin/include/eos/chain_plugin/chain_plugin.hpp index 26232d269..205259397 100644 --- a/plugins/chain_plugin/include/eos/chain_plugin/chain_plugin.hpp +++ b/plugins/chain_plugin/include/eos/chain_plugin/chain_plugin.hpp @@ -3,6 +3,7 @@ #include #include #include +#include #include @@ -22,6 +23,13 @@ struct empty{}; class read_only { const chain_controller& db; + const string KEYi64 = "i64"; + const string KEYi128i128 = "i128i128"; + const string KEYi64i64i64 = "i64i64i64"; + const string PRIMARY = "primary"; + const string SECONDARY = "secondary"; + const string TERTIARY = "tertiary"; + public: read_only(const chain_controller& db) : db(db) {} @@ -105,39 +113,86 @@ public: get_block_results get_block(const get_block_params& params) const; - struct get_table_rows_i64_params { + struct get_table_rows_params { bool json = false; Name scope; Name code; Name table; - uint64_t lower_bound = 0; - uint64_t upper_bound = uint64_t(-1); + string table_type; + string table_key; + string lower_bound; + string upper_bound; uint32_t limit = 10; - }; - - struct get_table_rows_i64_result { - vector rows; ///< one row per item, either encoded as hex String or JSON object - bool more; ///< true if last element in data is not the end and sizeof data() < limit - }; - - get_table_rows_i64_result get_table_rows_i64( const get_table_rows_i64_params& params )const; - - struct get_table_rows_i128i128_primary_params { - bool json = false; - Name scope; - Name code; - Name table; - uint128_t lower_bound = 0; - uint128_t upper_bound = uint128_t(-1); - uint32_t limit = 10; - }; + }; - struct get_table_rows_i128i128_primary_result { + struct get_table_rows_result { vector rows; ///< one row per item, either encoded as hex String or JSON object bool more; ///< true if last element in data is not the end and sizeof data() < limit }; - get_table_rows_i128i128_primary_result get_table_rows_i128i128_primary( const get_table_rows_i128i128_primary_params& params )const; + get_table_rows_result get_table_rows( const get_table_rows_params& params )const; + + void copy_row(const chain::key_value_object& obj, vector& data)const { + data.resize( sizeof(uint64_t) + obj.value.size() ); + memcpy( data.data(), &obj.primary_key, sizeof(uint64_t) ); + memcpy( data.data()+sizeof(uint64_t), obj.value.data(), obj.value.size() ); + } + + void copy_row(const chain::key128x128_value_object& obj, vector& data)const { + data.resize( 2*sizeof(uint128_t) + obj.value.size() ); + memcpy( data.data(), &obj.primary_key, sizeof(uint128_t) ); + memcpy( data.data()+sizeof(uint128_t), &obj.secondary_key, sizeof(uint128_t) ); + memcpy( data.data()+2*sizeof(uint128_t), obj.value.data(), obj.value.size() ); + } + + void copy_row(const chain::key64x64x64_value_object& obj, vector& data)const { + data.resize( 3*sizeof(uint64_t) + obj.value.size() ); + memcpy( data.data(), &obj.primary_key, sizeof(uint64_t) ); + memcpy( data.data()+sizeof(uint64_t), &obj.secondary_key, sizeof(uint64_t) ); + memcpy( data.data()+2*sizeof(uint64_t), &obj.tertiary_key, sizeof(uint64_t) ); + memcpy( data.data()+3*sizeof(uint64_t), obj.value.data(), obj.value.size() ); + } + + template + read_only::get_table_rows_result get_table_rows_ex( const read_only::get_table_rows_params& p )const { + read_only::get_table_rows_result result; + const auto& d = db.get_database(); + const auto& code_account = d.get( p.code ); + + types::AbiSerializer abis; + if( code_account.abi.size() > 4 ) { /// 4 == packsize of empty Abi + eos::types::Abi abi; + fc::datastream ds( code_account.abi.data(), code_account.abi.size() ); + fc::raw::unpack( ds, abi ); + abis.setAbi( abi ); + } + + const auto& idx = d.get_index(); + auto lower = idx.lower_bound( boost::make_tuple(p.scope, p.code, p.table, boost::lexical_cast(p.lower_bound)) ); + auto upper = idx.upper_bound( boost::make_tuple(p.scope, p.code, p.table, boost::lexical_cast(p.upper_bound)) ); + + vector data; + + auto start = fc::time_point::now(); + auto end = fc::time_point::now() + fc::microseconds( 1000*10 ); /// 10ms max time + + int count = 0; + auto itr = lower; + for( itr = lower; itr != upper && itr->table == p.table; ++itr ) { + copy_row(*itr, data); + + if( p.json ) + result.rows.emplace_back( abis.binaryToVariant( abis.getTableType(p.table), data ) ); + else + result.rows.emplace_back( fc::variant(data) ); + if( ++count == p.limit || fc::time_point::now() > end ) + break; + } + if( itr != upper ) + result.more = true; + return result; + } + }; class read_write { @@ -198,20 +253,16 @@ private: FC_REFLECT(eos::chain_apis::empty, ) FC_REFLECT(eos::chain_apis::read_only::get_info_results, - (head_block_num)(last_irreversible_block_num)(head_block_id)(head_block_time)(head_block_producer) - (recent_slots)(participation_rate)) + (head_block_num)(last_irreversible_block_num)(head_block_id)(head_block_time)(head_block_producer) + (recent_slots)(participation_rate)) FC_REFLECT(eos::chain_apis::read_only::get_block_params, (block_num_or_id)) - + FC_REFLECT_DERIVED( eos::chain_apis::read_only::get_block_results, (eos::chain::signed_block), (id)(block_num)(refBlockPrefix) ); FC_REFLECT( eos::chain_apis::read_write::push_transaction_results, (transaction_id)(processed) ) -FC_REFLECT( eos::chain_apis::read_only::get_table_rows_i64_params, - (json)(scope)(code)(table)(lower_bound)(upper_bound)(limit) ); -FC_REFLECT( eos::chain_apis::read_only::get_table_rows_i64_result, - (rows)(more) ); -FC_REFLECT( eos::chain_apis::read_only::get_table_rows_i128i128_primary_params, - (json)(scope)(code)(table)(lower_bound)(upper_bound)(limit) ); -FC_REFLECT( eos::chain_apis::read_only::get_table_rows_i128i128_primary_result, - (rows)(more) ); + +FC_REFLECT( eos::chain_apis::read_only::get_table_rows_params, (json)(table_type)(table_key)(scope)(code)(table)(lower_bound)(upper_bound)(limit) ) +FC_REFLECT( eos::chain_apis::read_only::get_table_rows_result, (rows)(more) ); + FC_REFLECT( eos::chain_apis::read_only::get_account_results, (name)(eos_balance)(staked_balance)(unstaking_balance)(last_unstaking_time)(producer)(abi) ) FC_REFLECT( eos::chain_apis::read_only::get_account_params, (name) ) FC_REFLECT( eos::chain_apis::read_only::producer_info, (name) ) -- GitLab