Skip to content

Commit a75421b

Browse files
committed
Merge remote-tracking branch 'url/dev_master' into testnet
2 parents e08218a + 832129f commit a75421b

File tree

9 files changed

+199
-39
lines changed

9 files changed

+199
-39
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
#include <graphenelib/contract.hpp>
2+
#include <graphenelib/dispatcher.hpp>
3+
#include <graphenelib/print.hpp>
4+
#include <graphenelib/types.h>
5+
#include <graphenelib/multi_index.hpp>
6+
#include <map>
7+
8+
using namespace graphene;
9+
10+
class testmapset : public contract
11+
{
12+
public:
13+
testmapset(uint64_t id)
14+
: contract(id), mapsettabs(_self, _self)
15+
{
16+
}
17+
18+
/// @abi action
19+
void mapaction(std::map<std::string,uint64_t> mappar)
20+
{
21+
auto itor = mappar.begin();
22+
auto str = itor->first;
23+
auto num = itor->second;
24+
for (int i = 0; i < 1; ++i) {
25+
print("str:",str,"\n");
26+
print("num:",num,"\n");
27+
28+
}
29+
uint64_t pk = mapsettabs.available_primary_key();
30+
mapsettabs.emplace(0, [&](auto &o) {
31+
o.id = pk;
32+
o.mymap = mappar;
33+
});
34+
}
35+
36+
// @abi action
37+
void setaction(std::set<std::string> setpar)
38+
{
39+
auto itor = setpar.begin();
40+
print("set: ",*itor,"\n");
41+
42+
uint64_t pk = mapsettabs.available_primary_key();
43+
mapsettabs.emplace(0, [&](auto &o) {
44+
o.id = pk;
45+
o.myset = setpar;
46+
});
47+
}
48+
49+
//@abi table mapsettab i64
50+
struct mapsettab {
51+
uint64_t id;
52+
std::map<std::string,uint64_t> mymap;
53+
std::set<std::string> myset;
54+
55+
uint64_t primary_key() const { return id; }
56+
57+
GRAPHENE_SERIALIZE(mapsettab, (id)(mymap)(myset))
58+
};
59+
60+
typedef graphene::multi_index<N(mapsettab), mapsettab> mapset_index;
61+
mapset_index mapsettabs;
62+
63+
};
64+
65+
GRAPHENE_ABI(testmapset, (mapaction)(setaction))

libraries/abi_generator/abi_generator.cpp

+76-1
Original file line numberDiff line numberDiff line change
@@ -446,13 +446,23 @@ bool abi_generator::is_vector(const clang::QualType& vqt) {
446446
qt = qt->getAs<clang::ElaboratedType>()->getNamedType();
447447

448448
return isa<clang::TemplateSpecializationType>(qt.getTypePtr()) \
449-
&& boost::starts_with( get_type_name(qt, false), "vector");
449+
&& (boost::starts_with( get_type_name(qt, false), "vector")||boost::starts_with( get_type_name(qt, false), "set"));
450450
}
451451

452452
bool abi_generator::is_vector(const string& type_name) {
453453
return boost::ends_with(type_name, "[]");
454454
}
455455

456+
bool abi_generator::is_map(const clang::QualType& mqt) {
457+
QualType qt(mqt);
458+
459+
if ( is_elaborated(qt) )
460+
qt = qt->getAs<clang::ElaboratedType>()->getNamedType();
461+
462+
return isa<clang::TemplateSpecializationType>(qt.getTypePtr()) \
463+
&& boost::starts_with( get_type_name(qt, false), "map");
464+
}
465+
456466
bool abi_generator::is_struct_specialization(const clang::QualType& qt) {
457467
return is_struct(qt) && isa<clang::TemplateSpecializationType>(qt.getTypePtr());
458468
}
@@ -476,6 +486,17 @@ string abi_generator::get_vector_element_type(const string& type_name) {
476486
return type_name;
477487
}
478488

489+
std::vector<clang::QualType> abi_generator::get_map_element_type(const clang::QualType& qt)
490+
{
491+
const auto* tst = clang::dyn_cast<const clang::TemplateSpecializationType>(qt.getTypePtr());
492+
ABI_ASSERT(tst != nullptr);
493+
const clang::TemplateArgument& arg0 = tst->getArg(0);
494+
const clang::TemplateArgument& arg1 = tst->getArg(1);
495+
std::vector<clang::QualType> varg;
496+
varg.emplace_back(arg0.getAsType());
497+
varg.emplace_back(arg1.getAsType());
498+
return varg;
499+
}
479500
string abi_generator::get_type_name(const clang::QualType& qt, bool with_namespace=false) {
480501
auto name = clang::TypeName::getFullyQualifiedName(qt, *ast_context);
481502
if(!with_namespace)
@@ -557,6 +578,7 @@ string abi_generator::add_vector(const clang::QualType& vqt, size_t recursion_de
557578

558579
auto vector_element_type = get_vector_element_type(qt);
559580
ABI_ASSERT(!is_vector(vector_element_type), "Only one-dimensional arrays are supported");
581+
ABI_ASSERT(!is_map(vector_element_type), "Only one-dimensional maps are supported");
560582

561583
add_type(vector_element_type, recursion_depth);
562584

@@ -566,6 +588,54 @@ string abi_generator::add_vector(const clang::QualType& vqt, size_t recursion_de
566588
return vector_element_type_str;
567589
}
568590

591+
string abi_generator::add_map(const clang::QualType& mqt, size_t recursion_depth)
592+
{
593+
ABI_ASSERT( ++recursion_depth < max_recursion_depth, "recursive definition, max_recursion_depth" );
594+
595+
clang::QualType qt(get_named_type_if_elaborated(mqt));
596+
597+
auto map_element_type_list = get_map_element_type(qt);
598+
ABI_ASSERT(!is_map(map_element_type_list[0]), "Only one-dimensional maps are supported");
599+
ABI_ASSERT(!is_map(map_element_type_list[1]), "Only one-dimensional maps are supported");
600+
601+
add_type(map_element_type_list[0], recursion_depth);
602+
add_type(map_element_type_list[1], recursion_depth);
603+
604+
std::string map_element_type_str_0;
605+
std::string map_element_type_str_1;
606+
if(is_vector(map_element_type_list[0]))
607+
map_element_type_str_0 = add_vector(map_element_type_list[0],recursion_depth);
608+
else
609+
map_element_type_str_0 = translate_type(get_type_name(map_element_type_list[0]));
610+
if(is_vector(map_element_type_list[1]))
611+
map_element_type_str_1 = add_vector(map_element_type_list[1],recursion_depth);
612+
else
613+
map_element_type_str_1 = translate_type(get_type_name(map_element_type_list[1]));
614+
615+
static uint64_t index = 1;
616+
std::string index_name = std::to_string(index);
617+
std::string map_element_type_str = "map" + index_name + "[]";
618+
index++;
619+
620+
// add struct
621+
struct_def map_def;
622+
map_def.name = map_element_type_str.substr(0, map_element_type_str.length() - 2);
623+
map_def.base = "";
624+
625+
std::string key_field_name = "key";
626+
std::string key_field_type_name = map_element_type_str_0;
627+
field_def key_struct_field{key_field_name, key_field_type_name};
628+
629+
std::string value_field_name = "value";
630+
std::string value_field_type_name = map_element_type_str_1;
631+
field_def value_struct_field{value_field_name, value_field_type_name};
632+
633+
map_def.fields.push_back(key_struct_field);
634+
map_def.fields.push_back(value_struct_field);
635+
636+
output->structs.push_back(map_def);
637+
return map_element_type_str;
638+
}
569639
string abi_generator::add_type(const clang::QualType& tqt, size_t recursion_depth) {
570640

571641
ABI_ASSERT( ++recursion_depth < max_recursion_depth, "recursive definition, max_recursion_depth" );
@@ -593,6 +663,11 @@ string abi_generator::add_type(const clang::QualType& tqt, size_t recursion_dept
593663
return is_type_def ? type_name : vector_type_name;
594664
}
595665

666+
if( is_map(qt) ){
667+
auto map_type_name = add_map(qt, recursion_depth);
668+
return is_type_def ? type_name : map_type_name;
669+
}
670+
596671
if( is_struct(qt) ) {
597672
return add_struct(qt, full_type_name, recursion_depth);
598673
}

libraries/abi_generator/include/graphene/abi_generator/abi_generator.hpp

+3
Original file line numberDiff line numberDiff line change
@@ -188,6 +188,8 @@ namespace graphene {
188188
bool is_vector(const string& type_name);
189189
string add_vector(const clang::QualType& qt, size_t recursion_depth);
190190

191+
bool is_map(const clang::QualType& qt);
192+
string add_map(const clang::QualType& qt, size_t recursion_depth);
191193
bool is_struct(const clang::QualType& qt);
192194
string add_struct(const clang::QualType& qt, string full_type_name, size_t recursion_depth);
193195

@@ -200,6 +202,7 @@ namespace graphene {
200202
QualType get_vector_element_type(const clang::QualType& qt);
201203
string get_vector_element_type(const string& type_name);
202204

205+
std::vector<clang::QualType> get_map_element_type(const clang::QualType& qt);
203206
clang::QualType get_named_type_if_elaborated(const clang::QualType& qt);
204207

205208
const clang::RecordDecl::field_range get_struct_fields(const clang::QualType& qt);

libraries/app/include/graphene/app/network_broadcast_api.hpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ namespace graphene { namespace app {
6161
* The transaction will be checked for validity in the local database prior to broadcasting. If it fails to
6262
* apply locally, an error will be thrown and the transaction will not be broadcast.
6363
*/
64-
void broadcast_transaction(const signed_transaction& trx);
64+
transaction_id_type broadcast_transaction(const signed_transaction& trx);
6565

6666
/** this version of broadcast transaction registers a callback method that will be called when the transaction is
6767
* included into a block. The callback method includes the transaction id, block number, and transaction number in the

libraries/app/network_broadcast_api.cpp

+2-1
Original file line numberDiff line numberDiff line change
@@ -57,14 +57,15 @@ namespace graphene { namespace app {
5757
}
5858
}
5959

60-
void network_broadcast_api::broadcast_transaction(const signed_transaction& trx)
60+
transaction_id_type network_broadcast_api::broadcast_transaction(const signed_transaction& trx)
6161
{
6262
dlog("received trx message ${trx}",("trx",trx));
6363

6464
trx.validate();
6565
_app.chain_database()->push_transaction(trx);// evaluatet trx
6666
if (_app.p2p_node() != nullptr)
6767
_app.p2p_node()->broadcast_transaction(trx); // broadcast trx
68+
return trx.id();
6869
}
6970

7071
fc::variant network_broadcast_api::broadcast_transaction_synchronous(const signed_transaction& trx)

libraries/chain/db_update.cpp

+2-2
Original file line numberDiff line numberDiff line change
@@ -96,13 +96,13 @@ void database::update_global_dynamic_data( const signed_block& b )
9696

9797
if( !(get_node_properties().skip_flags & skip_undo_history_check) )
9898
{
99-
GRAPHENE_ASSERT( head_number - _dgp.last_irreversible_block_num < GRAPHENE_MAX_UNDO_HISTORY, undo_database_exception,
99+
GRAPHENE_ASSERT( _dgp.head_block_number - _dgp.last_irreversible_block_num < GRAPHENE_MAX_UNDO_HISTORY, undo_database_exception,
100100
"The database does not have enough undo history to support a blockchain with so many missed blocks. "
101101
"Please add a checkpoint if you would like to continue applying blocks beyond this point.",
102102
("last_irreversible_block_num",_dgp.last_irreversible_block_num)("head", _dgp.head_block_number)
103103
("recently_missed",_dgp.recently_missed_count)("max_undo",GRAPHENE_MAX_UNDO_HISTORY) );
104104
}
105-
_undo_db.set_max_size(head_number - _dgp.last_irreversible_block_num + 1);
105+
_undo_db.set_max_size(_dgp.head_block_number - _dgp.last_irreversible_block_num + 1);
106106
_fork_db.set_max_size(head_number - _dgp.last_irreversible_block_num + 1);
107107
}
108108

libraries/plugins/elasticsearch/elasticsearch_plugin.cpp

+30-21
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ class elasticsearch_plugin_impl
6060
std::string _elasticsearch_index_prefix = "gxchain";
6161
bool _elasticsearch_operation_object = true;
6262
uint32_t _elasticsearch_start_es_after_block = 0;
63+
uint64_t _elasticsearch_max_ops_per_account = 0;
6364
CURL *curl; // curl handler
6465
vector <string> bulk_lines; // vector of op lines
6566
vector<std::string> prepare;
@@ -322,27 +323,31 @@ void elasticsearch_plugin_impl::cleanObjects(const account_transaction_history_i
322323
{
323324
graphene::chain::database& db = database();
324325
// remove everything except current object from ath
325-
const auto &his_idx = db.get_index_type<account_transaction_history_index>();
326-
const auto &by_seq_idx = his_idx.indices().get<by_seq>();
327-
auto itr = by_seq_idx.lower_bound(boost::make_tuple(account_id, 0));
328-
if (itr != by_seq_idx.end() && itr->account == account_id && itr->id != ath_id) {
329-
// if found, remove the entry
330-
const auto remove_op_id = itr->operation_id;
331-
const auto itr_remove = itr;
332-
++itr;
333-
db.remove( *itr_remove );
334-
// modify previous node's next pointer
335-
// this should be always true, but just have a check here
336-
if( itr != by_seq_idx.end() && itr->account == account_id )
337-
{
338-
db.modify( *itr, [&]( account_transaction_history_object& obj ){
339-
obj.next = account_transaction_history_id_type();
340-
});
341-
}
342-
// do the same on oho
343-
const auto &by_opid_idx = his_idx.indices().get<by_opid>();
344-
if (by_opid_idx.find(remove_op_id) == by_opid_idx.end()) {
345-
db.remove(remove_op_id(db));
326+
const auto& stats_obj = account_id(db).statistics(db);
327+
if( stats_obj.total_ops - stats_obj.removed_ops > _elasticsearch_max_ops_per_account )
328+
{
329+
const auto &his_idx = db.get_index_type<account_transaction_history_index>();
330+
const auto &by_seq_idx = his_idx.indices().get<by_seq>();
331+
auto itr = by_seq_idx.lower_bound(boost::make_tuple(account_id, 0));
332+
if (itr != by_seq_idx.end() && itr->account == account_id && itr->id != ath_id) {
333+
// if found, remove the entry
334+
const auto remove_op_id = itr->operation_id;
335+
const auto itr_remove = itr;
336+
++itr;
337+
db.remove( *itr_remove );
338+
// modify previous node's next pointer
339+
// this should be always true, but just have a check here
340+
if( itr != by_seq_idx.end() && itr->account == account_id )
341+
{
342+
db.modify( *itr, [&]( account_transaction_history_object& obj ){
343+
obj.next = account_transaction_history_id_type();
344+
});
345+
}
346+
// do the same on oho
347+
const auto &by_opid_idx = his_idx.indices().get<by_opid>();
348+
if (by_opid_idx.find(remove_op_id) == by_opid_idx.end()) {
349+
db.remove(remove_op_id(db));
350+
}
346351
}
347352
}
348353
}
@@ -392,6 +397,7 @@ void elasticsearch_plugin::plugin_set_program_options(
392397
("elasticsearch-index-prefix", boost::program_options::value<std::string>(), "Add a prefix to the index(gxchain)")
393398
("elasticsearch-operation-object", boost::program_options::value<bool>(), "Save operation as object(true)")
394399
("elasticsearch-start-es-after-block", boost::program_options::value<uint32_t>(), "Start doing ES job after block(0)")
400+
("elasticsearch-max-ops-per-account", boost::program_options::value<uint64_t>(), "Maximum number of operations per account will be kept in memory")
395401
;
396402
cfg.add(cli);
397403
}
@@ -428,6 +434,9 @@ void elasticsearch_plugin::plugin_initialize(const boost::program_options::varia
428434
if (options.count("elasticsearch-start-es-after-block")) {
429435
my->_elasticsearch_start_es_after_block = options["elasticsearch-start-es-after-block"].as<uint32_t>();
430436
}
437+
if (options.count("elasticsearch-max-ops-per-account")) {
438+
my->_elasticsearch_max_ops_per_account = options["elasticsearch-max-ops-per-account"].as<uint64_t>();
439+
}
431440
}
432441

433442
void elasticsearch_plugin::plugin_startup()

libraries/plugins/query_txid/CMakeLists.txt

+16-9
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,22 @@ file(GLOB HEADERS "include/graphene/query_txid/*.hpp")
33
add_library( graphene_query_txid
44
query_txid_plugin.cpp
55
)
6+
find_path(LevelDB_INCLUDE_PATH NAMES leveldb/db.h leveldb/write_batch.h)
7+
find_library(LevelDB_LIBRARY NAMES libleveldb.a)
8+
find_library(Snappy_LIBRARY NAMES libsnappy.a)
69

7-
target_link_libraries( graphene_query_txid graphene_chain graphene_app leveldb)
8-
target_include_directories( graphene_query_txid
9-
PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/include" )
10+
if(LevelDB_INCLUDE_PATH AND LevelDB_LIBRARY AND Snappy_LIBRARY)
11+
target_link_libraries( graphene_query_txid graphene_chain graphene_app ${LevelDB_LIBRARY} ${Snappy_LIBRARY})
12+
target_include_directories( graphene_query_txid
13+
PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/include" ${LevelDB_INCLUDE_PATH})
14+
install( TARGETS
15+
graphene_query_txid
1016

11-
install( TARGETS
12-
graphene_query_txid
17+
RUNTIME DESTINATION bin
18+
LIBRARY DESTINATION lib
19+
ARCHIVE DESTINATION lib
20+
)
21+
else(LevelDB_INCLUDE_PATH AND LevelDB_LIBRARY AND Snappy_LIBRARY)
22+
message(FATAL_ERROR "You need leveldb and snappy")
23+
endif()
1324

14-
RUNTIME DESTINATION bin
15-
LIBRARY DESTINATION lib
16-
ARCHIVE DESTINATION lib
17-
)

libraries/plugins/query_txid/query_txid_plugin.cpp

+4-4
Original file line numberDiff line numberDiff line change
@@ -42,19 +42,19 @@ class query_txid_plugin_impl
4242
fc::signal<void()> sig_db_write;
4343
fc::signal<void(const uint64_t)> sig_remove;
4444

45-
static DB *leveldb;
45+
static leveldb::DB *leveldb;
4646
void consume_block(); //Consume block
4747
void remove_trx_index(const uint64_t trx_entry_id); //Remove trx_index in db
4848
};
49-
DB *query_txid_plugin_impl::leveldb = nullptr;
49+
leveldb::DB *query_txid_plugin_impl::leveldb = nullptr;
5050

5151
void query_txid_plugin_impl::init()
5252
{
5353
try {
5454
//Create leveldb
55-
Options options;
55+
leveldb::Options options;
5656
options.create_if_missing = true;
57-
Status s = DB::Open(options, db_path, &leveldb);
57+
leveldb::Status s = leveldb::DB::Open(options, db_path, &leveldb);
5858

5959
// Respond to the sig_db_write signale
6060
sig_db_write.connect([&]() { consume_block(); });

0 commit comments

Comments
 (0)