Skip to content

Commit

Permalink
[RocksDB] Do not fill block cache from iterators (#2858)
Browse files Browse the repository at this point in the history
  • Loading branch information
wezrule authored Jul 27, 2020
1 parent ad21727 commit a3324c6
Show file tree
Hide file tree
Showing 5 changed files with 70 additions and 74 deletions.
75 changes: 39 additions & 36 deletions nano/node/rocksdb/rocksdb.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -62,16 +62,6 @@ rocksdb_config (rocksdb_config_a)
}
}

nano::rocksdb_store::~rocksdb_store ()
{
for (auto handle : handles)
{
delete handle;
}

delete db;
}

void nano::rocksdb_store::open (bool & error_a, boost::filesystem::path const & path_a, bool open_read_only_a)
{
std::initializer_list<const char *> names{ rocksdb::kDefaultColumnFamilyName.c_str (), "frontiers", "accounts", "blocks", "pending", "representation", "unchecked", "vote", "online_weight", "meta", "peers", "cached_counts", "confirmation_height" };
Expand All @@ -84,19 +74,28 @@ void nano::rocksdb_store::open (bool & error_a, boost::filesystem::path const &
auto options = get_db_options ();
rocksdb::Status s;

std::vector<rocksdb::ColumnFamilyHandle *> handles_l;
if (open_read_only_a)
{
s = rocksdb::DB::OpenForReadOnly (options, path_a.string (), column_families, &handles, &db);
rocksdb::DB * db_l;
s = rocksdb::DB::OpenForReadOnly (options, path_a.string (), column_families, &handles_l, &db_l);
db.reset (db_l);
}
else
{
s = rocksdb::OptimisticTransactionDB::Open (options, path_a.string (), column_families, &handles, &optimistic_db);
s = rocksdb::OptimisticTransactionDB::Open (options, path_a.string (), column_families, &handles_l, &optimistic_db);
if (optimistic_db)
{
db = optimistic_db;
db.reset (optimistic_db);
}
}

handles.resize (handles_l.size ());
for (auto i = 0; i < handles_l.size (); ++i)
{
handles[i].reset (handles_l[i]);
}

// Assign handles to supplied
error_a |= !s.ok ();

Expand Down Expand Up @@ -134,7 +133,7 @@ nano::write_transaction nano::rocksdb_store::tx_begin_write (std::vector<nano::t

nano::read_transaction nano::rocksdb_store::tx_begin_read ()
{
return nano::read_transaction{ std::make_unique<nano::read_rocksdb_txn> (db) };
return nano::read_transaction{ std::make_unique<nano::read_rocksdb_txn> (db.get ()) };
}

std::string nano::rocksdb_store::vendor_get () const
Expand All @@ -146,11 +145,11 @@ rocksdb::ColumnFamilyHandle * nano::rocksdb_store::table_to_column_family (table
{
auto & handles_l = handles;
auto get_handle = [&handles_l](const char * name) {
auto iter = std::find_if (handles_l.begin (), handles_l.end (), [name](auto handle) {
auto iter = std::find_if (handles_l.begin (), handles_l.end (), [name](auto & handle) {
return (handle->GetName () == name);
});
debug_assert (iter != handles_l.end ());
return *iter;
return (*iter).get ();
};

switch (table_a)
Expand Down Expand Up @@ -194,6 +193,7 @@ bool nano::rocksdb_store::exists (nano::transaction const & transaction_a, table
else
{
rocksdb::ReadOptions options;
options.fill_cache = false;
status = tx (transaction_a)->Get (options, table_to_column_family (table_a), key_a, &slice);
}

Expand Down Expand Up @@ -423,14 +423,15 @@ int nano::rocksdb_store::clear (rocksdb::ColumnFamilyHandle * column_family)
auto name = column_family->GetName ();
auto status = db->DropColumnFamily (column_family);
release_assert (status.ok ());
delete column_family;

// Need to add it back as we just want to clear the contents
auto handle_it = std::find (handles.begin (), handles.end (), column_family);
auto handle_it = std::find_if (handles.begin (), handles.end (), [column_family](auto & handle) {
return handle.get () == column_family;
});
debug_assert (handle_it != handles.cend ());
status = db->CreateColumnFamily (get_cf_options (), name, &column_family);
release_assert (status.ok ());
*handle_it = column_family;
handle_it->reset (column_family);
return status.code ();
}

Expand Down Expand Up @@ -540,7 +541,7 @@ bool nano::rocksdb_store::copy_db (boost::filesystem::path const & destination_p
}
}

auto status = backup_engine->CreateNewBackup (db);
auto status = backup_engine->CreateNewBackup (db.get ());
if (!status.ok ())
{
return false;
Expand All @@ -558,27 +559,29 @@ bool nano::rocksdb_store::copy_db (boost::filesystem::path const & destination_p
}
}

rocksdb::BackupEngineReadOnly * backup_engine_read;
status = rocksdb::BackupEngineReadOnly::Open (rocksdb::Env::Default (), rocksdb::BackupableDBOptions (destination_path.string ()), &backup_engine_read);
if (!status.ok ())
{
delete backup_engine_read;
return false;
}
std::unique_ptr<rocksdb::BackupEngineReadOnly> backup_engine_read;
{
rocksdb::BackupEngineReadOnly * backup_engine_read_raw;
status = rocksdb::BackupEngineReadOnly::Open (rocksdb::Env::Default (), rocksdb::BackupableDBOptions (destination_path.string ()), &backup_engine_read_raw);
}
if (!status.ok ())
{
return false;
}

// First remove all files (not directories) in the destination
for (boost::filesystem::directory_iterator end_dir_it, it (destination_path); it != end_dir_it; ++it)
{
auto path = it->path ();
if (boost::filesystem::is_regular_file (path))
// First remove all files (not directories) in the destination
for (auto const & path : boost::make_iterator_range (boost::filesystem::directory_iterator (destination_path)))
{
boost::filesystem::remove (it->path ());
if (boost::filesystem::is_regular_file (path))
{
boost::filesystem::remove (path);
}
}
}

// Now generate the relevant files from the backup
status = backup_engine->RestoreDBFromLatestBackup (destination_path.string (), destination_path.string ());
delete backup_engine_read;
// Now generate the relevant files from the backup
status = backup_engine->RestoreDBFromLatestBackup (destination_path.string (), destination_path.string ());
}

// Open it so that it flushes all WAL files
if (status.ok ())
Expand Down
9 changes: 4 additions & 5 deletions nano/node/rocksdb/rocksdb.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@ class rocksdb_store : public block_store_partial<rocksdb::Slice, rocksdb_store>
{
public:
rocksdb_store (nano::logger_mt &, boost::filesystem::path const &, nano::rocksdb_config const & = nano::rocksdb_config{}, bool open_read_only = false);
~rocksdb_store ();
nano::write_transaction tx_begin_write (std::vector<nano::tables> const & tables_requiring_lock = {}, std::vector<nano::tables> const & tables_no_lock = {}) override;
nano::read_transaction tx_begin_read () override;

Expand All @@ -52,24 +51,24 @@ class rocksdb_store : public block_store_partial<rocksdb::Slice, rocksdb_store>
template <typename Key, typename Value>
nano::store_iterator<Key, Value> make_iterator (nano::transaction const & transaction_a, tables table_a) const
{
return nano::store_iterator<Key, Value> (std::make_unique<nano::rocksdb_iterator<Key, Value>> (db, transaction_a, table_to_column_family (table_a)));
return nano::store_iterator<Key, Value> (std::make_unique<nano::rocksdb_iterator<Key, Value>> (db.get (), transaction_a, table_to_column_family (table_a)));
}

template <typename Key, typename Value>
nano::store_iterator<Key, Value> make_iterator (nano::transaction const & transaction_a, tables table_a, nano::rocksdb_val const & key) const
{
return nano::store_iterator<Key, Value> (std::make_unique<nano::rocksdb_iterator<Key, Value>> (db, transaction_a, table_to_column_family (table_a), key));
return nano::store_iterator<Key, Value> (std::make_unique<nano::rocksdb_iterator<Key, Value>> (db.get (), transaction_a, table_to_column_family (table_a), &key));
}

bool init_error () const override;

private:
bool error{ false };
nano::logger_mt & logger;
std::vector<rocksdb::ColumnFamilyHandle *> handles;
// Optimistic transactions are used in write mode
rocksdb::OptimisticTransactionDB * optimistic_db = nullptr;
rocksdb::DB * db = nullptr;
std::unique_ptr<rocksdb::DB> db;
std::vector<std::unique_ptr<rocksdb::ColumnFamilyHandle>> handles;
std::shared_ptr<rocksdb::TableFactory> table_factory;
std::unordered_map<nano::tables, std::mutex> write_lock_mutexes;

Expand Down
48 changes: 18 additions & 30 deletions nano/node/rocksdb/rocksdb_iterator.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,10 @@ inline bool is_read (nano::transaction const & transaction_a)
return (dynamic_cast<const nano::read_transaction *> (&transaction_a) != nullptr);
}

inline rocksdb::ReadOptions const & snapshot_options (nano::transaction const & transaction_a)
inline rocksdb::ReadOptions & snapshot_options (nano::transaction const & transaction_a)
{
debug_assert (is_read (transaction_a));
return *static_cast<const rocksdb::ReadOptions *> (transaction_a.get_handle ());
return *static_cast<rocksdb::ReadOptions *> (transaction_a.get_handle ());
}
}

Expand All @@ -31,50 +31,33 @@ template <typename T, typename U>
class rocksdb_iterator : public store_iterator_impl<T, U>
{
public:
rocksdb_iterator (rocksdb::DB * db, nano::transaction const & transaction_a, rocksdb::ColumnFamilyHandle * handle_a)
rocksdb_iterator () = default;

rocksdb_iterator (rocksdb::DB * db, nano::transaction const & transaction_a, rocksdb::ColumnFamilyHandle * handle_a, rocksdb_val const * val_a)
{
// Don't fill the block cache for any blocks read as a result of an iterator
rocksdb::Iterator * iter;
if (is_read (transaction_a))
{
iter = db->NewIterator (snapshot_options (transaction_a), handle_a);
auto & read_options = snapshot_options (transaction_a);
read_options.fill_cache = false;
cursor.reset (db->NewIterator (read_options, handle_a));
}
else
{
rocksdb::ReadOptions ropts;
ropts.fill_cache = false;
iter = tx (transaction_a)->GetIterator (ropts, handle_a);
cursor.reset (tx (transaction_a)->GetIterator (ropts, handle_a));
}

cursor.reset (iter);
cursor->SeekToFirst ();

if (cursor->Valid ())
if (val_a)
{
current.first.value = cursor->key ();
current.second.value = cursor->value ();
cursor->Seek (*val_a);
}
else
{
clear ();
cursor->SeekToFirst ();
}
}

rocksdb_iterator () = default;

rocksdb_iterator (rocksdb::DB * db, nano::transaction const & transaction_a, rocksdb::ColumnFamilyHandle * handle_a, rocksdb_val const & val_a)
{
rocksdb::Iterator * iter;
if (is_read (transaction_a))
{
iter = db->NewIterator (snapshot_options (transaction_a), handle_a);
}
else
{
iter = tx (transaction_a)->GetIterator (rocksdb::ReadOptions (), handle_a);
}

cursor.reset (iter);
cursor->Seek (val_a);

if (cursor->Valid ())
{
Expand All @@ -87,6 +70,11 @@ class rocksdb_iterator : public store_iterator_impl<T, U>
}
}

rocksdb_iterator (rocksdb::DB * db, nano::transaction const & transaction_a, rocksdb::ColumnFamilyHandle * handle_a) :
rocksdb_iterator (db, transaction_a, handle_a, nullptr)
{
}

rocksdb_iterator (nano::rocksdb_iterator<T, U> && other_a)
{
cursor = other_a.cursor;
Expand Down
10 changes: 8 additions & 2 deletions nano/node/rocksdb/rocksdb_txn.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,10 @@
nano::read_rocksdb_txn::read_rocksdb_txn (rocksdb::DB * db_a) :
db (db_a)
{
options.snapshot = db_a->GetSnapshot ();
if (db_a)
{
options.snapshot = db_a->GetSnapshot ();
}
}

nano::read_rocksdb_txn::~read_rocksdb_txn ()
Expand All @@ -13,7 +16,10 @@ nano::read_rocksdb_txn::~read_rocksdb_txn ()

void nano::read_rocksdb_txn::reset ()
{
db->ReleaseSnapshot (options.snapshot);
if (db)
{
db->ReleaseSnapshot (options.snapshot);
}
}

void nano::read_rocksdb_txn::renew ()
Expand Down
2 changes: 1 addition & 1 deletion nano/secure/blockstore_partial.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -360,7 +360,7 @@ class block_store_partial : public block_store
nano::db_val<Val> data;
auto status = get (transaction_a, tables::meta, nano::db_val<Val> (version_key), data);
int result (minimum_version);
if (!not_found (status))
if (success (status))
{
nano::uint256_union version_value (data);
debug_assert (version_value.qwords[2] == 0 && version_value.qwords[1] == 0 && version_value.qwords[0] == 0);
Expand Down

0 comments on commit a3324c6

Please sign in to comment.