Repository navigation
Kvapi rocksdb nodeos integration first working version check in - #9340
brianjohnson5972 merged 8 commits into
Conversation
…-scenarios-test.py while chain_kv is reevaluated
… accomadate change of state memory layout
| std::vector<char> prefix = rocksdb_contract_kv_prefix; | ||
| b1::chain_kv::append_key(prefix, kvdisk_id.to_uint64_t()); | ||
| it->Seek(b1::chain_kv::to_slice(rocksdb_contract_kv_prefix)); | ||
| while(it->Valid()) { |
There was a problem hiding this comment.
It would be nice if the rocksdb::Iterator supported the appropriate iterator concept to allow for range base for loops. This might be something that we could wrap within chain_kv.
There was a problem hiding this comment.
I think we should wait on these. @revl needs to make several changes for this.
| if ( header.version < kv_object::minimum_snapshot_version ) | ||
| return; | ||
| if (conf.use_rocksdb_for_disk) { | ||
| rocksdb::WriteBatch batch; |
There was a problem hiding this comment.
My opinion is that the controller should have no direct dependency on rocksdb types. Can this functionality be pushed down into the chain_kv api?
There was a problem hiding this comment.
yes, and @revl will handle this after this PR is committed.
| snapshot->write_section<value_t>([this]( auto& section ){ | ||
| // This ordering depends on the fact the eosio.kvdisk is before eosio.kvram and only eosio.kvdisk can be stored in rocksdb. | ||
| if (db.get<kv_db_config_object>().using_rocksdb_for_disk) { | ||
| std::unique_ptr<rocksdb::Iterator> it{kv_database.rdb->NewIterator(rocksdb::ReadOptions())}; |
There was a problem hiding this comment.
Could this functionality be pushed down into chain_kv?
There was a problem hiding this comment.
@linhuang-blockone apply my comment about leaving refactoring for @revl for all these comments about pushing this down into chain_kv. @revl and @TimothyBanks can work this out later.
| chainbase::database& controller::mutable_db()const { return my->db; } | ||
|
|
||
| const fork_database& controller::fork_db()const { return my->fork_db; } | ||
| b1::chain_kv::database& controller::kv_database() { return my->kv_database; } |
There was a problem hiding this comment.
Is there any need for a const overload of this method?
There was a problem hiding this comment.
Whether or not there is, I think @revl should look at that. Lin doesn't need to do it here since what he has implemented obviously isn't needing it.
There was a problem hiding this comment.
(from Lin) Cannot add const here, as db and undo_stack parameters in create_kv_rocksdb_context are non-const.
|
|
||
| const fork_database& controller::fork_db()const { return my->fork_db; } | ||
| b1::chain_kv::database& controller::kv_database() { return my->kv_database; } | ||
| b1::chain_kv::undo_stack& controller::kv_undo_stack() { return my->kv_undo_stack; } |
There was a problem hiding this comment.
Is there any need for a const overload of this method?
There was a problem hiding this comment.
create_kv_rocksdb_context() needs kv_database and kv_undo_stack as argutments but kv_database() and kv_undo_stack() aren't accessible because they are private.
There was a problem hiding this comment.
not following why @kimjh2005 thinks this, since the code does that and it compiles
| auto kv = kv_it.get_kv(); | ||
|
|
||
| // kv is always non-null due to the check of is_valid() | ||
| *found_key_size = kv->key.size(); |
There was a problem hiding this comment.
Who is responsible for the null check on found_key_size and found_value_size?
| kv_resource_manager resource_manager; | ||
| const kv_database_config& limits; | ||
| uint32_t num_iterators = 0; | ||
| std::shared_ptr<const std::vector<char>> temp_data_buffer; |
There was a problem hiding this comment.
Who is this shared with?
| }; // kv_iterator_rocksdb | ||
|
|
||
| struct kv_context_rocksdb : kv_context { | ||
| b1::chain_kv::database& database; |
There was a problem hiding this comment.
I'm just wanting to make sure that there are guarantees that make sure the database (and undo stack below) stay in scope with the kv_context.
There was a problem hiding this comment.
kv_context_rocksdb is created and destroyed by apply_context, which is created and destroyed by controller. Controller creates the database on startup and destroys it on shutdown.
| } | ||
| FC_LOG_AND_RETHROW() | ||
| } | ||
| CATCH_AND_EXIT_DB_FAILURE() |
There was a problem hiding this comment.
Are we sure we want to terminate the program?
There was a problem hiding this comment.
If this isn't a refactoring from the existing code, then we definitely cannot
| } | ||
| FC_LOG_AND_RETHROW() | ||
| } | ||
| CATCH_AND_EXIT_DB_FAILURE() |
There was a problem hiding this comment.
One last time, do these warrant program termination?
| #include <eosio/chain/types.hpp> | ||
|
|
||
| namespace eosio { namespace chain { | ||
| class kv_db_config_object : public chainbase::object<kv_db_config_object_type, kv_db_config_object> { |
There was a problem hiding this comment.
Since KV and DB storage will always be the same (either both in RocksDB or both in chainbase), this object should be named something like backing_storage_config_object and should be defined in an *_objects file that isn't specific to KV. (In general we should avoid using "db" in anything refering to RocksDB vs chainbase, since we use kv and db to distinguish the intrinsics)
| OBJECT_CTOR(kv_db_config_object) | ||
|
|
||
| id_type id; | ||
| bool using_rocksdb_for_disk = false; |
There was a problem hiding this comment.
need to drop the "_for_disk" extension here, on the similarly named functions, and elsewhere
There was a problem hiding this comment.
I think it would be good to make this an enum that is called "backing_storage" with the default value being chain_base, and could be set to rocks_db. This way if we add other backing stores in the future, we could just add them here, instead of having a new parameter and having to validate that parameter's value doesn't conflict with this parameter's value.
| if (db.get<kv_db_config_object>().using_rocksdb_for_disk) | ||
| return; | ||
| auto& idx = db.get_index<kv_index, by_kv_key>(); | ||
| auto it = idx.lower_bound(boost::make_tuple(kvdisk_id, name{}, std::string_view{})); |
There was a problem hiding this comment.
These should all be kvram_id and eosio.kvram
| composite_key_compare<std::less<name>, std::less<name>, unsigned_blob_less>>>>; | ||
|
|
||
| inline void use_rocksdb_for_disk(chainbase::database& db) { | ||
| if (db.get<kv_db_config_object>().using_rocksdb_for_disk) |
There was a problem hiding this comment.
store off db.get<kv_db_config_object>() in a variable and use the variable here and below
| kv_iterators.resize(1); | ||
| kv_destroyed_iterators.clear(); | ||
| if (!context_free) { | ||
| #warning TODO: Remove kv_ram. Rename kv_disk |
There was a problem hiding this comment.
fix this comment and switch code below to be for kv_ram instead of kv_disk
| } | ||
|
|
||
| // skip the kv_db_config as it only determines where the kv-database is stored | ||
| if (std::is_same_v<value_t, kv_db_config_object>) { |
There was a problem hiding this comment.
Remove this. If you don't add it to the using definition (above) for controller_index_set, then it won't be present in the walk_indices.
| if constexpr (std::is_same_v<value_t, kv_object>) { | ||
| if ( header.version < kv_object::minimum_snapshot_version ) | ||
| return; | ||
| if (conf.use_rocksdb_for_disk) { |
There was a problem hiding this comment.
Same issue that I mentioned in writing snapshot section above, if you have a kv_object then we are using chainbase as the backing store and use_rocksdb won't be set. The check should be used after reading the data, before determining if you should write to the rocksdb (key value) backing store or the chainbase backing store. That code should be through an abstraction, that takes the snapshot data and then there will be a chainbase implementation or a rocksdb (key value) implementation (not sure if this would go in kv_context_*** or not, it probably can)
| // Currently kv_undo_stack returns a wrong revision after restart, | ||
| // failing tests/terminate-scenarios-test.py. | ||
| // As chain_kv is being rewritten, comment out this check for now | ||
| // and retest after chain_kv rewriting is finished. |
There was a problem hiding this comment.
Has Timothy been made aware of this problem in kv_undo_stack?
| class kv_tester : public tester { | ||
| public: | ||
| kv_tester() { | ||
| eosio::chain::use_rocksdb_for_disk(const_cast<chainbase::database&>(control->db())); |
There was a problem hiding this comment.
fix indentation, and why don't you use your helper method you added?
There was a problem hiding this comment.
And this line means that kv_tester only tests kv with rockdb and not chainbase. To test both you can use BOOST_AUTO_TEST_CASE_TEMPLATE below and make kv_tester templated on backend_store (chainbase, rocksdb - see other comment about use_rocksdb_for_disk not being a bool) . See snapshot_tests.cpp for examples of how to use.
| // BOOST_TEST(iterlimit({{N(eosio.kvram), 0xFFFFFFFF, false}, {N(eosio.kvdisk), 1, false}}) == "Too many iterators"); | ||
| } | ||
|
|
||
| // Make sure that a failed transaction correctly rolls back changes to the database, |
There was a problem hiding this comment.
now I see what you are doing. Use my suggestion above, revert these methods and the BOOST_AUTO_TEST_CASE_TEMPLATE will take care of testing both chainbase and rocksdb.
There was a problem hiding this comment.
or you cans use BOOST_DATA_TEST_CASE_F, but no reason that I can see to repeat all these tests 3 times, unless I am missing something.
31c34f7 to
513e0e1
Compare
brianjohnson5972
left a comment
There was a problem hiding this comment.
Checking this PR in as-is and @linhuang-blockone will be breaking up the cleanup into their own individual PRs.
Change Description
This PR checks in the first KV API RocksDB working version, serving as a baseline example for the team. All new test cases have passed. Comments from Bucky at the review meeting have not yet been incorporated. They are marked by "#warning: TODO" so compiler will generate a warning and we will not forget. Please pay attention to them as they represent new direction. I will incorporate them in my next PR.
Change Type
Select ONE
Consensus Changes
API Changes
Documentation Additions