Skip to content

Commit 1ee29e1

Browse files
committed
store abi def in chainbase
1 parent c07a4f9 commit 1ee29e1

File tree

6 files changed

+149
-143
lines changed

6 files changed

+149
-143
lines changed

CMakeLists.txt

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ file(GLOB HEADERS "include/eosio/elasticsearch_plugin/*.hpp")
22
add_library( elasticsearch_plugin
33
elasticsearch_plugin.cpp
44
elastic_client.cpp
5-
deserializer.cpp
65
bulker.cpp
76
${HEADERS} )
87

README.md

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -142,4 +142,3 @@ Config Options for eosio::elasticsearch_plugin.
142142
## TODO
143143

144144
- [ ] Due to `libcurl` [100-continue feature](https://curl.haxx.se/mail/lib-2017-07/0013.html), consider replace [EOSLaoMao/elasticlient](https://github.com/EOSLaoMao/elasticlient) with other simple http client like [https://cpp-netlib.org/#](https://cpp-netlib.org/#)
145-
- [ ] Currently, the plugin will cache all abi information in the RAM. It's not a issue for now. Maybe it is better to embed some LRU cache library in the feature.

deserializer.cpp

Lines changed: 0 additions & 77 deletions
This file was deleted.

deserializer.hpp

Lines changed: 0 additions & 49 deletions
This file was deleted.

elasticsearch_plugin.cpp

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@
2929
#include "elastic_client.hpp"
3030
#include "exceptions.hpp"
3131
#include "mappings.hpp"
32-
#include "deserializer.hpp"
32+
#include "serializer.hpp"
3333
#include "bulker.hpp"
3434
#include "ThreadPool/ThreadPool.h"
3535

@@ -126,10 +126,6 @@ class elasticsearch_plugin_impl {
126126
bool store_transaction_traces = true;
127127
bool store_action_traces = true;
128128

129-
std::unique_ptr<elastic_client> es_client;
130-
std::unique_ptr<deserializer> abi_deserializer;
131-
std::unique_ptr<bulker_pool> bulk_pool;
132-
std::unique_ptr<ThreadPool> thread_pool;
133129
size_t max_task_queue_size = 0;
134130
int task_queue_sleep_time = 0;
135131

@@ -153,6 +149,11 @@ class elasticsearch_plugin_impl {
153149
boost::atomic<bool> startup{true};
154150
fc::optional<chain::chain_id_type> chain_id;
155151

152+
std::unique_ptr<elastic_client> es_client;
153+
std::unique_ptr<serializer> serializer;
154+
std::unique_ptr<bulker_pool> bulk_pool;
155+
std::unique_ptr<ThreadPool> thread_pool;
156+
156157
static const action_name newaccount;
157158
static const action_name setabi;
158159
static const action_name updateauth;
@@ -507,7 +508,7 @@ void elasticsearch_plugin_impl::upsert_account_setabi(
507508
{
508509
abi_def abi_def = fc::raw::unpack<chain::abi_def>( setabi.abi );
509510

510-
abi_deserializer->upsert_abi_cache( setabi.account, abi_def );
511+
serializer->upsert_abi_cache( setabi.account, abi_def );
511512

512513
param_doc("name", setabi.account.to_string());
513514
param_doc("abi", abi_def);
@@ -687,7 +688,7 @@ void elasticsearch_plugin_impl::_process_applied_transaction( chain::transaction
687688
for (auto& atrace : base_action_traces) {
688689
fc::mutable_variant_object action_traces_doc;
689690
chain::base_action_trace &base = atrace.get();
690-
fc::from_variant( abi_deserializer->to_variant_with_abi( base ), action_traces_doc );
691+
fc::from_variant( serializer->to_variant_with_abi( base ), action_traces_doc );
691692

692693
fc::mutable_variant_object act_doc;
693694
fc::from_variant( action_traces_doc["act"], act_doc );
@@ -699,7 +700,7 @@ void elasticsearch_plugin_impl::_process_applied_transaction( chain::transaction
699700
fc::mutable_variant_object action_doc;
700701
action_doc("_index", action_traces_index);
701702
action_doc("_type", "_doc");
702-
action_doc("_id", action_traces_doc["receipt"]["global_sequence"]);
703+
action_doc("_id", base.receipt.global_sequence);
703704
action_doc("retry_on_conflict", 100);
704705

705706
auto action = fc::json::to_string( fc::variant_object("index", action_doc) );
@@ -713,7 +714,7 @@ void elasticsearch_plugin_impl::_process_applied_transaction( chain::transaction
713714
// transaction trace index
714715

715716
fc::mutable_variant_object trans_traces_doc;
716-
fc::from_variant( abi_deserializer->to_variant_with_abi( *t ), trans_traces_doc );
717+
fc::from_variant( serializer->to_variant_with_abi( *t ), trans_traces_doc );
717718
trans_traces_doc("createAt", now.count());
718719

719720
fc::mutable_variant_object action_doc;
@@ -751,7 +752,7 @@ void elasticsearch_plugin_impl::_process_accepted_transaction( chain::transactio
751752
auto now = std::chrono::duration_cast<std::chrono::milliseconds>(
752753
std::chrono::microseconds{fc::time_point::now().time_since_epoch().count()} );
753754

754-
fc::from_variant( abi_deserializer->to_variant_with_abi( trx ), trans_doc );
755+
fc::from_variant( serializer->to_variant_with_abi( trx ), trans_doc );
755756
trans_doc("trx_id", trx_id_str);
756757

757758
fc::variant signing_keys;
@@ -794,7 +795,7 @@ void elasticsearch_plugin_impl::_process_accepted_block( chain::block_state_ptr
794795
[ bs{std::move(bs)}, this ]()
795796
{
796797
auto block_num = bs->block_num;
797-
if( block_num % 1000 == 0 )
798+
if( block_num % 10000 == 0 )
798799
ilog( "block_num: ${b}", ("b", block_num) );
799800

800801
const auto block_id = bs->id;
@@ -856,7 +857,7 @@ void elasticsearch_plugin_impl::_process_accepted_block( chain::block_state_ptr
856857

857858
params_doc("block_num", static_cast<int32_t>(block_num));
858859
params_doc("block_id", block_id_str);
859-
params_doc("block", abi_deserializer->to_variant_with_abi( *bs->block ));
860+
params_doc("block", serializer->to_variant_with_abi( *bs->block ));
860861
params_doc("irreversible", false);
861862
params_doc("createAt", now.count());
862863

@@ -946,15 +947,14 @@ void elasticsearch_plugin_impl::_process_irreversible_block(chain::block_state_p
946947

947948
block_doc("block_num", static_cast<int32_t>(block_num));
948949
block_doc("block_id", block_id_str);
949-
block_doc("block", abi_deserializer->to_variant_with_abi( *bs->block ));
950+
block_doc("block", serializer->to_variant_with_abi( *bs->block ));
950951
block_doc("irreversible", true);
951952
block_doc("validated", bs->validated);
952953
block_doc("createAt", now.count());
953954

954955
doc("script", script_doc);
955956
doc("upsert", block_doc);
956957

957-
958958
fc::mutable_variant_object action_doc;
959959
action_doc("_index", blocks_index);
960960
action_doc("_type", "_doc");
@@ -1238,7 +1238,7 @@ void elasticsearch_plugin::plugin_initialize(const variables_map& options) {
12381238
EOS_ASSERT(max_time > chain::config::default_abi_serializer_max_time_ms,
12391239
chain::plugin_config_exception, "--abi-serializer-max-time-ms required as default value not appropriate for parsing full blocks");
12401240
fc::microseconds abi_serializer_max_time = app().get_plugin<chain_plugin>().get_abi_serializer_max_time();
1241-
my->abi_deserializer.reset( new deserializer( abi_serializer_max_time ));
1241+
my->serializer.reset( new serializer( app().data_dir() / "abi", abi_serializer_max_time ));
12421242
}
12431243

12441244
if( options.count( "elastic-queue-size" )) {

serializer.hpp

Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,134 @@
1+
#pragma once
2+
#include <eosio/chain/multi_index_includes.hpp>
3+
#include <eosio/chain/database_utils.hpp>
4+
5+
using namespace eosio;
6+
using namespace chainbase;
7+
8+
struct by_account;
9+
10+
class abi_cache: public chainbase::object<0, abi_cache> {
11+
OBJECT_CTOR(abi_cache,(abi))
12+
13+
id_type id;
14+
account_name account;
15+
eosio::chain::shared_blob abi;
16+
17+
void set_abi( const eosio::chain::abi_def& a ) {
18+
abi.resize( fc::raw::pack_size( a ) );
19+
fc::datastream<char*> ds( abi.data(), abi.size() );
20+
fc::raw::pack( ds, a );
21+
}
22+
};
23+
24+
25+
using abi_cache_index_t = chainbase::shared_multi_index_container<abi_cache,
26+
indexed_by<
27+
ordered_unique< member<abi_cache,abi_cache::id_type,&abi_cache::id> >,
28+
ordered_unique< tag<by_account>, member<abi_cache,account_name,&abi_cache::account> >
29+
>
30+
>;
31+
32+
CHAINBASE_SET_INDEX_TYPE( abi_cache, abi_cache_index_t )
33+
34+
35+
class serializer
36+
{
37+
public:
38+
serializer(const bfs::path& dir, fc::microseconds abi_serializer_max_time)
39+
:db(dir, database::read_write, 1024*1024*8), abi_serializer_max_time(abi_serializer_max_time)
40+
{
41+
db.add_index<abi_cache_index_t>();
42+
}
43+
44+
optional<abi_serializer> get_abi_serializer( const account_name &name ) {
45+
if( name.good() ) {
46+
try {
47+
const auto& a = db.get<abi_cache, by_account>(name);
48+
abi_def abi;
49+
if( abi_serializer::to_abi( a.abi, abi ))
50+
return abi_def_to_serializer(name, abi);
51+
} catch( std::out_of_range& e) {
52+
// ignore missing abi excepton.
53+
} FC_CAPTURE_AND_LOG((name))
54+
}
55+
return optional<abi_serializer>();
56+
}
57+
58+
template<typename T>
59+
fc::variant to_variant_with_abi( const T& obj ) {
60+
fc::variant pretty_output;
61+
abi_serializer::to_variant( obj, pretty_output,
62+
[&]( account_name n ) { return get_abi_serializer( n ); },
63+
abi_serializer_max_time );
64+
return pretty_output;
65+
}
66+
67+
void upsert_abi_cache( const account_name &name, const abi_def& abi ) {
68+
if( name.good()) {
69+
try {
70+
auto* a = db.find<abi_cache, by_account>(name);
71+
if ( a == nullptr ) {
72+
db.create<abi_cache>( [&]( abi_cache& ca ) {
73+
ca.account = name;
74+
ca.set_abi(abi);
75+
});
76+
} else {
77+
db.modify( *a, [&]( abi_cache& ca ) {
78+
ca.set_abi(abi);
79+
});
80+
}
81+
} FC_CAPTURE_AND_LOG((name))
82+
}
83+
}
84+
85+
private:
86+
87+
chainbase::database db;
88+
fc::microseconds abi_serializer_max_time;
89+
90+
optional<abi_serializer> abi_def_to_serializer( const account_name &name, const abi_def& abi ) {
91+
if( name.good()) {
92+
try {
93+
abi_serializer abis;
94+
95+
if( name == chain::config::system_account_name ) {
96+
// redefine eosio setabi.abi from bytes to abi_def
97+
// Done so that abi is stored as abi_def in elasticsearch instead of as bytes
98+
abi_def abi_new = abi;
99+
auto itr = std::find_if( abi_new.structs.begin(), abi_new.structs.end(),
100+
[]( const auto& s ) { return s.name == "setabi"; } );
101+
if( itr != abi_new.structs.end() ) {
102+
auto itr2 = std::find_if( itr->fields.begin(), itr->fields.end(),
103+
[]( const auto& f ) { return f.name == "abi"; } );
104+
if( itr2 != itr->fields.end() ) {
105+
if( itr2->type == "bytes" ) {
106+
itr2->type = "abi_def";
107+
// unpack setabi.abi as abi_def instead of as bytes
108+
abis.add_specialized_unpack_pack( "abi_def",
109+
std::make_pair<abi_serializer::unpack_function, abi_serializer::pack_function>(
110+
[]( fc::datastream<const char*>& stream, bool is_array, bool is_optional ) -> fc::variant {
111+
EOS_ASSERT( !is_array && !is_optional, chain::elasticsearch_exception, "unexpected abi_def");
112+
chain::bytes temp;
113+
fc::raw::unpack( stream, temp );
114+
return fc::variant( fc::raw::unpack<abi_def>( temp ) );
115+
},
116+
[]( const fc::variant& var, fc::datastream<char*>& ds, bool is_array, bool is_optional ) {
117+
EOS_ASSERT( false, chain::elasticsearch_exception, "never called" );
118+
}
119+
) );
120+
}
121+
}
122+
}
123+
abis.set_abi( abi_new, abi_serializer_max_time );
124+
} else {
125+
abis.set_abi( abi, abi_serializer_max_time );
126+
}
127+
128+
return abis;
129+
} FC_CAPTURE_AND_LOG((name))
130+
}
131+
return optional<abi_serializer>();
132+
}
133+
134+
};

0 commit comments

Comments
 (0)