Skip to content

Commit

Permalink
Merge pull request #38 from volbil/rabbit
Browse files Browse the repository at this point in the history
Generic event handler interface
  • Loading branch information
volbil authored Apr 18, 2021
2 parents 4c5d331 + 0095ac6 commit 8e3c371
Show file tree
Hide file tree
Showing 36 changed files with 443 additions and 178 deletions.
3 changes: 2 additions & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -194,7 +194,8 @@ set(SERVER_SOURCES
./src/httprpc.cpp
./src/httpserver.cpp
./src/init.cpp
./src/interface/wallet.cpp
./src/interfaces/handler.cpp
./src/interfaces/wallet.cpp
./src/dbwrapper.cpp
./src/legacy/validation_zerocoin_legacy.cpp
./src/main.cpp
Expand Down
2 changes: 1 addition & 1 deletion configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ dnl require autoconf 2.60 (AS_ECHO/AS_ECHO_N)
AC_PREREQ([2.60])
define(_CLIENT_VERSION_MAJOR, 4)
define(_CLIENT_VERSION_MINOR, 0)
define(_CLIENT_VERSION_REVISION, 1)
define(_CLIENT_VERSION_REVISION, 2)
define(_CLIENT_VERSION_BUILD, 0)
define(_CLIENT_VERSION_RC, 0)
define(_CLIENT_VERSION_IS_RELEASE, true)
Expand Down
6 changes: 4 additions & 2 deletions src/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -199,7 +199,8 @@ BITCOIN_CORE_H = \
httprpc.h \
httpserver.h \
init.h \
interface/wallet.h \
interfaces/handler.h \
interfaces/wallet.h \
invalid.h \
invalid_outpoints.json.h \
invalid_serials.json.h \
Expand Down Expand Up @@ -372,7 +373,7 @@ libbitcoin_wallet_a_SOURCES = \
activemasternode.cpp \
bip38.cpp \
denomination_functions.cpp \
interface/wallet.cpp \
interfaces/wallet.cpp \
addressbook.cpp \
crypter.cpp \
key_io.cpp \
Expand Down Expand Up @@ -548,6 +549,7 @@ libbitcoin_util_a_SOURCES = \
compat/glibcxx_sanity.cpp \
compat/strnlen.cpp \
fs.cpp \
interfaces/handler.cpp \
logging.cpp \
random.cpp \
rpc/protocol.cpp \
Expand Down
103 changes: 70 additions & 33 deletions src/init.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -779,6 +779,18 @@ bool AppInitServers()
std::terminate();
};

namespace { // Variables internal to initialization process only

ServiceFlags nRelevantServices = NODE_NETWORK;
int nMaxConnections;
int nUserMaxConnections;
int nFD;
ServiceFlags nLocalServices = NODE_NETWORK;

std::string strWalletFile;
bool fDisableWallet = false;
}

bool AppInitBasicSetup()
{
// ********************************************************* Step 1: setup
Expand Down Expand Up @@ -979,24 +991,17 @@ void InitLogging()
LogPrintf("RPD version %s (%s)\n", version_string, CLIENT_DATE);
}

/** Initialize pivx.
* @pre Parameters should be parsed and config file should be read.
*/
bool AppInit2()
bool AppInitParameterInteraction()
{
// ********************************************************* Step 1: setup
if (!AppInitBasicSetup())
return false;

// ********************************************************* Step 2: parameter interactions
// Make sure enough file descriptors are available
int nBind = std::max((int)mapArgs.count("-bind") + (int)mapArgs.count("-whitebind"), 1);
int nUserMaxConnections = GetArg("-maxconnections", DEFAULT_MAX_PEER_CONNECTIONS);
int nMaxConnections = std::max(nUserMaxConnections, 0);
nUserMaxConnections = GetArg("-maxconnections", DEFAULT_MAX_PEER_CONNECTIONS);
nMaxConnections = std::max(nUserMaxConnections, 0);

// Trim requested connection counts, to fit into system limitations
nMaxConnections = std::max(std::min(nMaxConnections, (int)(FD_SETSIZE - nBind - MIN_CORE_FILEDESCRIPTORS)), 0);
int nFD = RaiseFileDescriptorLimit(nMaxConnections + MIN_CORE_FILEDESCRIPTORS);
nFD = RaiseFileDescriptorLimit(nMaxConnections + MIN_CORE_FILEDESCRIPTORS);
if (nFD < MIN_CORE_FILEDESCRIPTORS)
return UIError(_("Not enough file descriptors available."));
if (nFD - MIN_CORE_FILEDESCRIPTORS < nMaxConnections)
Expand Down Expand Up @@ -1104,17 +1109,14 @@ bool AppInit2()
}

#ifdef ENABLE_WALLET
std::string strWalletFile = GetArg("-wallet", DEFAULT_WALLET_DAT);
strWalletFile = GetArg("-wallet", DEFAULT_WALLET_DAT);
if (!CWallet::ParameterInteraction())
return false;
#endif // ENABLE_WALLET

fIsBareMultisigStd = GetBoolArg("-permitbaremultisig", DEFAULT_PERMIT_BAREMULTISIG);
nMaxDatacarrierBytes = GetArg("-datacarriersize", nMaxDatacarrierBytes);

ServiceFlags nLocalServices = NODE_NETWORK;
ServiceFlags nRelevantServices = NODE_NETWORK;

if (GetBoolArg("-peerbloomfilters", DEFAULT_PEERBLOOMFILTERS))
nLocalServices = ServiceFlags(nLocalServices | NODE_BLOOM);

Expand All @@ -1123,7 +1125,39 @@ bool AppInit2()
if (!InitNUParams())
return false;

// ********************************************************* Step 4: application initialization: dir lock, daemonize, pidfile, debug log
return true;
}

static bool LockDataDirectory(bool probeOnly)
{
std::string strDataDir = GetDataDir().string();

// Make sure only a single RPD process is using the data directory.
fs::path pathLockFile = GetDataDir() / ".lock";
FILE* file = fsbridge::fopen(pathLockFile, "a"); // empty lock file; created if it doesn't exist.
if (file) fclose(file);

try {
static boost::interprocess::file_lock lock(pathLockFile.string().c_str());
// Wait maximum 10 seconds if an old wallet is still running. Avoids lockup during restart
if (!lock.timed_lock(boost::get_system_time() + boost::posix_time::seconds(10))) {
return UIError(strprintf(_("Cannot obtain a lock on data directory %s. %s is probably already running."),
strDataDir, _(PACKAGE_NAME)));
}
if (probeOnly) {
lock.unlock();
}
} catch (const boost::interprocess::interprocess_exception& e) {
return UIError(
strprintf(_("Cannot obtain a lock on data directory %s. %s is probably already running.") + " %s.",
strDataDir, _(PACKAGE_NAME), e.what()));
}
return true;
}

bool AppInitSanityChecks()
{
// ********************************************************* Step 4: sanity checks

// Initialize elliptic curve code
RandomInit();
Expand All @@ -1132,19 +1166,22 @@ bool AppInit2()

// Sanity check
if (!InitSanityCheck())
return UIError(_("Initialization sanity check failed. Rapids Core is shutting down."));
return UIError(strprintf(_("Initialization sanity check failed. %s is shutting down."), _(PACKAGE_NAME)));

std::string strDataDir = GetDataDir().string();

// Make sure only a single RPD process is using the data directory.
fs::path pathLockFile = GetDataDir() / ".lock";
FILE* file = fsbridge::fopen(pathLockFile, "a"); // empty lock file; created if it doesn't exist.
if (file) fclose(file);
static boost::interprocess::file_lock lock(pathLockFile.string().c_str());
// Probe the data directory lock to give an early error message, if possible
return LockDataDirectory(true);
}

// Wait maximum 10 seconds if an old wallet is still running. Avoids lockup during restart
if (!lock.timed_lock(boost::get_system_time() + boost::posix_time::seconds(10)))
return UIError(strprintf(_("Cannot obtain a lock on data directory %s. Rapids Core is probably already running."), strDataDir));
bool AppInitMain()
{
// ********************************************************* Step 4a: application initialization
// After daemonization get the data directory lock again and hold on to it until exit
// This creates a slight window for a race condition to happen, however this condition is harmless: it
// will at most make us exit without printing a message to console.
if (!LockDataDirectory(false)) {
// Detailed error printed inside LockDataDirectory
return false;
}

#ifndef WIN32
CreatePidFile(GetPidFile(), getpid());
Expand All @@ -1161,7 +1198,7 @@ bool AppInit2()
if (!g_logger->m_log_timestamps)
LogPrintf("Startup time: %s\n", DateTimeStrFormat("%Y-%m-%d %H:%M:%S", GetTime()));
LogPrintf("Default data directory %s\n", GetDefaultDataDir().string());
LogPrintf("Using data directory %s\n", strDataDir);
LogPrintf("Using data directory %s\n", GetDataDir().string());
LogPrintf("Using config file %s\n", GetConfigFile().string());
LogPrintf("Using at most %i connections (%i file descriptors available)\n", nMaxConnections, nFD);
std::ostringstream strErrors;
Expand All @@ -1181,8 +1218,8 @@ bool AppInit2()
}

// Start the lightweight task scheduler thread
CScheduler::Function serviceLoop = boost::bind(&CScheduler::serviceQueue, &scheduler);
threadGroup.create_thread(boost::bind(&TraceThread<CScheduler::Function>, "scheduler", serviceLoop));
CScheduler::Function serviceLoop = std::bind(&CScheduler::serviceQueue, &scheduler);
threadGroup.create_thread(std::bind(&TraceThread<CScheduler::Function>, "scheduler", serviceLoop));

if (Params().IsRegTestNet()) { // only for regtest for now
// Initialize Sapling circuit parameters
Expand Down Expand Up @@ -1750,7 +1787,7 @@ bool AppInit2()
for (std::string strFile : mapMultiArgs["-loadblock"])
vImportFiles.push_back(strFile);
}
threadGroup.create_thread(boost::bind(&ThreadImport, vImportFiles));
threadGroup.create_thread(std::bind(&ThreadImport, vImportFiles));

// Wait for genesis block to be processed
LogPrintf("Waiting for genesis block to be imported...\n");
Expand Down Expand Up @@ -1900,7 +1937,7 @@ bool AppInit2()
LogPrintf("nSwiftTXDepth %d\n", nSwiftTXDepth);
LogPrintf("Budget Mode %s\n", strBudgetMode.c_str());

threadGroup.create_thread(boost::bind(&ThreadCheckMasternodes));
threadGroup.create_thread(std::bind(&ThreadCheckMasternodes));

if (ShutdownRequested()) {
LogPrintf("Shutdown requested. Exiting.\n");
Expand Down Expand Up @@ -1966,7 +2003,7 @@ bool AppInit2()

// StakeMiner thread disabled by default on regtest
if (GetBoolArg("-staking", !Params().IsRegTestNet() && DEFAULT_STAKING)) {
threadGroup.create_thread(boost::bind(&ThreadStakeMinter));
threadGroup.create_thread(std::bind(&ThreadStakeMinter));
}
}
#endif
Expand Down
19 changes: 18 additions & 1 deletion src/init.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,13 +28,30 @@ void PrepareShutdown();
void InitLogging();
//!Parameter interaction: change current parameters depending on various rules
void InitParameterInteraction();
bool AppInit2();

/** Initialize RPD core: Basic context setup.
* @note This can be done before daemonization. Do not call Shutdown() if this function fails.
* @pre Parameters should be parsed and config file should be read.
*/
bool AppInitBasicSetup();
/**
* Initialization: parameter interaction.
* @note This can be done before daemonization.
* @pre Parameters should be parsed and config file should be read, AppInitBasicSetup should have been called.
*/
bool AppInitParameterInteraction();
/**
* Initialization sanity checks: ecc init, sanity checks, dir lock.
* @note This can be done before daemonization.
* @pre Parameters should be parsed and config file should be read, AppInitParameterInteraction should have been called.
*/
bool AppInitSanityChecks();
/**
* Bitcoin core main initialization.
* @note This should only be done after daemonization.
* @pre Parameters should be parsed and config file should be read, AppInitSanityChecks should have been called.
*/
bool AppInitMain();

/** The help message mode determines what help message to show */
enum HelpMessageMode {
Expand Down
34 changes: 34 additions & 0 deletions src/interfaces/handler.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@

// Copyright (c) 2018-2020 The Bitcoin Core developers
// Copyright (c) 2020 The PIVX Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or https://www.opensource.org/licenses/mit-license.php.

#include <interfaces/handler.h>

#include <util/memory.h>

#include <boost/signals2/connection.hpp>
#include <utility>

namespace interfaces {
namespace {

class HandlerImpl : public Handler
{
public:
explicit HandlerImpl(boost::signals2::connection connection) : m_connection(std::move(connection)) {}

void disconnect() override { m_connection.disconnect(); }

boost::signals2::scoped_connection m_connection;
};

} // namespace

std::unique_ptr<Handler> MakeHandler(boost::signals2::connection connection)
{
return MakeUnique<HandlerImpl>(std::move(connection));
}

} // namespace interfaces
37 changes: 37 additions & 0 deletions src/interfaces/handler.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@

// Copyright (c) 2018-2020 The Bitcoin Core developers
// Copyright (c) 2020 The PIVX Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or https://www.opensource.org/licenses/mit-license.php.

#ifndef RAPIDS_INTERFACES_HANDLER_H
#define RAPIDS_INTERFACES_HANDLER_H

#include <memory>

namespace boost {
namespace signals2 {
class connection;
} // namespace signals2
} // namespace boost

namespace interfaces {

//! Generic interface for managing an event handler or callback function
//! registered with another interface. Has a single disconnect method to cancel
//! the registration and prevent any future notifications.
class Handler
{
public:
virtual ~Handler() {}

//! Disconnect the handler.
virtual void disconnect() = 0;
};

//! Return handler wrapping a boost signal connection.
std::unique_ptr<Handler> MakeHandler(boost::signals2::connection connection);

} // namespace interfaces

#endif // RAPIDS_INTERFACES_HANDLER_H
2 changes: 1 addition & 1 deletion src/interface/wallet.cpp → src/interfaces/wallet.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
// Distributed under the MIT software license, see the accompanying
// file COPYING or https://www.opensource.org/licenses/mit-license.php.

#include "interface/wallet.h"
#include "interfaces/wallet.h"
#include "wallet.h"

namespace interfaces {
Expand Down
File renamed without changes.
2 changes: 1 addition & 1 deletion src/miner.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -751,7 +751,7 @@ void GenerateBitcoins(bool fGenerate, CWallet* pwallet, int nThreads)

minerThreads = new boost::thread_group();
for (int i = 0; i < nThreads; i++)
minerThreads->create_thread(boost::bind(&ThreadBitcoinMiner, pwallet));
minerThreads->create_thread(std::bind(&ThreadBitcoinMiner, pwallet));
}

// ppcoin: stake minter thread
Expand Down
2 changes: 1 addition & 1 deletion src/net.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2173,7 +2173,7 @@ bool CConnman::Start(CScheduler& scheduler, std::string& strNodeError, Options c
threadMessageHandler = std::thread(&TraceThread<std::function<void()> >, "msghand", std::function<void()>(std::bind(&CConnman::ThreadMessageHandler, this)));

// Dump network addresses
scheduler.scheduleEvery(boost::bind(&CConnman::DumpData, this), DUMP_ADDRESSES_INTERVAL);
scheduler.scheduleEvery(std::bind(&CConnman::DumpData, this), DUMP_ADDRESSES_INTERVAL);

return true;
}
Expand Down
Loading

0 comments on commit 8e3c371

Please sign in to comment.