core: prevent the database from being used by multiple daemons

A boost lock is used to determine whether more than one process
wants to access the database. The boost file_lock doesn't seem
to like locking directories, so we use an arbitrary file in it.
This allows to still run two daemons if they have different
database directories (ie, LMDB/BDB, different data directories).
This commit is contained in:
moneromooo-monero 2016-01-31 12:58:08 +00:00
parent b91fc2dc3c
commit 8b3539bc11
No known key found for this signature in database
GPG Key ID: 686F07454D6CEFC3
2 changed files with 46 additions and 0 deletions

View File

@ -218,6 +218,39 @@ namespace cryptonote
return m_blockchain_storage.get_alternative_blocks_count(); return m_blockchain_storage.get_alternative_blocks_count();
} }
//----------------------------------------------------------------------------------------------- //-----------------------------------------------------------------------------------------------
bool core::lock_db_directory(const boost::filesystem::path &path)
{
// boost doesn't like locking directories...
const boost::filesystem::path lock_path = path / ".daemon_lock";
try
{
// ensure the file exists
std::ofstream(lock_path.string(), std::ios::out).close();
db_lock = boost::interprocess::file_lock(lock_path.string().c_str());
LOG_PRINT_L1("Locking " << lock_path.string());
if (!db_lock.try_lock())
{
LOG_PRINT_L0("Failed to lock " << lock_path.string());
return false;
}
return true;
}
catch (const std::exception &e)
{
LOG_PRINT_L0("Error trying to lock " << lock_path.string() << ": " << e.what());
return false;
}
}
//-----------------------------------------------------------------------------------------------
bool core::unlock_db_directory()
{
db_lock.unlock();
db_lock = boost::interprocess::file_lock();
return true;
}
//-----------------------------------------------------------------------------------------------
bool core::init(const boost::program_options::variables_map& vm) bool core::init(const boost::program_options::variables_map& vm)
{ {
bool r = handle_command_line(vm); bool r = handle_command_line(vm);
@ -280,6 +313,13 @@ namespace cryptonote
folder /= db->get_db_name(); folder /= db->get_db_name();
LOG_PRINT_L0("Loading blockchain from folder " << folder.string() << " ..."); LOG_PRINT_L0("Loading blockchain from folder " << folder.string() << " ...");
if (!lock_db_directory (folder))
{
LOG_ERROR ("Failed to lock " << folder);
delete db;
return false;
}
const std::string filename = folder.string(); const std::string filename = folder.string();
// temporarily default to fastest:async:1000 // temporarily default to fastest:async:1000
blockchain_db_sync_mode sync_mode = db_async; blockchain_db_sync_mode sync_mode = db_async;
@ -398,6 +438,7 @@ namespace cryptonote
{ {
m_blockchain_storage.deinit(); m_blockchain_storage.deinit();
} }
unlock_db_directory();
return true; return true;
} }
//----------------------------------------------------------------------------------------------- //-----------------------------------------------------------------------------------------------

View File

@ -34,6 +34,7 @@
#include <boost/program_options/options_description.hpp> #include <boost/program_options/options_description.hpp>
#include <boost/program_options/variables_map.hpp> #include <boost/program_options/variables_map.hpp>
#include <boost/interprocess/sync/file_lock.hpp>
#include "p2p/net_node_common.h" #include "p2p/net_node_common.h"
#include "cryptonote_protocol/cryptonote_protocol_handler_common.h" #include "cryptonote_protocol/cryptonote_protocol_handler_common.h"
@ -172,6 +173,8 @@ namespace cryptonote
void graceful_exit(); void graceful_exit();
bool check_fork_time(); bool check_fork_time();
bool relay_txpool_transactions(); bool relay_txpool_transactions();
bool lock_db_directory(const boost::filesystem::path &path);
bool unlock_db_directory();
static std::atomic<bool> m_fast_exit; static std::atomic<bool> m_fast_exit;
bool m_test_drop_download = true; bool m_test_drop_download = true;
@ -205,6 +208,8 @@ namespace cryptonote
time_t m_last_json_checkpoints_update; time_t m_last_json_checkpoints_update;
std::atomic_flag m_checkpoints_updating; std::atomic_flag m_checkpoints_updating;
boost::interprocess::file_lock db_lock;
}; };
} }