Ensure database resizing works well in a multithreaded context.

This commit is contained in:
clemahieu 2015-08-30 16:43:40 -05:00
commit 9e1eeccbc0
4 changed files with 37 additions and 20 deletions

View file

@ -16,6 +16,5 @@ enum class rai_networks
};
rai::rai_networks const rai_network = rai_networks::ACTIVE_NETWORK;
int const database_check_interval = rai_network == rai::rai_networks::rai_test_network ? 4 : 1024;
size_t const database_free_space = 16 * 1024 * 1024;
size_t const database_size_increment = rai_network == rai::rai_networks::rai_test_network ? 2 * 1024 * 1024 : 256 * 1024 * 1024;
}

View file

@ -121,14 +121,25 @@ TEST (wallet, multithreaded_send)
TEST (store, load)
{
rai::system system (24000, 1);
for (auto i (0); i != 10000; ++i)
std::vector <std::thread> threads;
for (auto i (0); i < 100; ++i)
{
rai::transaction transaction (system.nodes [0]->store.environment, nullptr, true);
for (auto j (0); j != 1000; ++j)
threads.push_back (std::thread ([&system] ()
{
rai::block_hash hash;
rai::random_pool.GenerateBlock (hash.bytes.data (), hash.bytes.size ());
system.nodes [0]->store.account_put (transaction, hash, rai::account_info ());
}
for (auto i (0); i != 1000; ++i)
{
rai::transaction transaction (system.nodes [0]->store.environment, nullptr, true);
for (auto j (0); j != 10; ++j)
{
rai::block_hash hash;
rai::random_pool.GenerateBlock (hash.bytes.data (), hash.bytes.size ());
system.nodes [0]->store.account_put (transaction, hash, rai::account_info ());
}
}
}));
}
for (auto &i: threads)
{
i.join ();
}
}

View file

@ -45,7 +45,8 @@ bool rai::from_string_hex (std::string const & value_a, uint64_t & target_a)
}
rai::mdb_env::mdb_env (bool & error_a, boost::filesystem::path const & path_a) :
counter (0),
open_transactions (0),
transaction_iteration (0),
resizing (false)
{
boost::system::error_code error;
@ -58,6 +59,8 @@ resizing (false)
assert (status1 == 0);
auto status2 (mdb_env_set_maxdbs (environment, 128));
assert (status2 == 0);
auto status3 (mdb_env_set_mapsize (environment, database_size_increment));
assert (status3 == 0);
auto status4 (mdb_env_open (environment, path_a.string ().c_str (), MDB_NOSUBDIR, 00600));
error_a = status4 != 0;
}
@ -92,9 +95,9 @@ void rai::mdb_env::add_transaction ()
std::unique_lock <std::mutex> lock_l (lock);
while (resizing)
{
condition.wait (lock_l);
resize_notify.wait (lock_l);
}
if ((counter % rai::database_check_interval) == 0)
if ((transaction_iteration % rai::database_check_interval) == 0)
{
MDB_stat stats;
mdb_env_stat (environment, &stats);
@ -102,26 +105,28 @@ void rai::mdb_env::add_transaction ()
mdb_env_info (environment, &info);
size_t load (info.me_last_pgno * stats.ms_psize);
auto slack (info.me_mapsize - load);
if (slack < rai::database_free_space)
if (slack < (rai::database_size_increment / 4))
{
resizing = true;
while (counter > 0)
while (open_transactions > 0)
{
condition.wait (lock_l);
open_notify.wait (lock_l);
}
auto next_size (((info.me_mapsize / database_size_increment) + 1) * database_size_increment);
mdb_env_set_mapsize (environment, next_size);
resizing = false;
resize_notify.notify_all ();
}
}
++counter;
++transaction_iteration;
++open_transactions;
}
void rai::mdb_env::remove_transaction ()
{
std::lock_guard <std::mutex> lock_l (lock);
--counter;
condition.notify_all ();
--open_transactions;
open_notify.notify_all ();
}
rai::mdb_val::mdb_val (size_t size_a, void * data_a) :
@ -150,8 +155,8 @@ environment (environment_a)
rai::transaction::~transaction ()
{
environment.remove_transaction ();
auto status (mdb_txn_commit (handle));
environment.remove_transaction ();
assert (status == 0);
}

View file

@ -66,8 +66,10 @@ public:
void remove_transaction ();
MDB_env * environment;
std::mutex lock;
std::condition_variable condition;
int counter;
std::condition_variable open_notify;
unsigned open_transactions;
unsigned transaction_iteration;
std::condition_variable resize_notify;
bool resizing;
};
class mdb_val