Merge pull request #7112

9af5f9c Move uiInterface.NotifyBlockTip signal above the core/wallet signal - This will keep getbestblockhash more in sync with blocknotify callbacks (Jonas Schnelli)
4082e46 [Qt] call GuessVerificationProgress synchronous during core signal, pass double over UI signal (Jonas Schnelli)
947d20b [Qt] reduce cs_main in getVerificationProgress() (Jonas Schnelli)
e6d50fc [Qt] update block tip (height and date) without locking cs_main, update always (each block) (Jonas Schnelli)
012fc91 NotifyBlockTip signal: switch from hash (uint256) to CBlockIndex* - also adds a boolean for indication if the tip update was happening during initial sync - emit notification also during initial sync (Jonas Schnelli)
This commit is contained in:
Wladimir J. van der Laan 2015-11-30 12:58:01 +01:00
commit 96b802510d
No known key found for this signature in database
GPG key ID: 74810B012346C9A6
10 changed files with 83 additions and 80 deletions

View file

@ -515,11 +515,14 @@ std::string LicenseInfo()
"\n"; "\n";
} }
static void BlockNotifyCallback(const uint256& hashNewTip) static void BlockNotifyCallback(bool initialSync, const CBlockIndex *pBlockIndex)
{ {
if (initialSync || !pBlockIndex)
return;
std::string strCmd = GetArg("-blocknotify", ""); std::string strCmd = GetArg("-blocknotify", "");
boost::replace_all(strCmd, "%s", hashNewTip.GetHex()); boost::replace_all(strCmd, "%s", pBlockIndex->GetBlockHash().GetHex());
boost::thread t(runCommand, strCmd); // thread runs free boost::thread t(runCommand, strCmd); // thread runs free
} }

View file

@ -2606,6 +2606,10 @@ bool ActivateBestChain(CValidationState &state, const CChainParams& chainparams,
// When we reach this point, we switched to a new tip (stored in pindexNewTip). // When we reach this point, we switched to a new tip (stored in pindexNewTip).
// Notifications/callbacks that can run without cs_main // Notifications/callbacks that can run without cs_main
// Always notify the UI if a new block tip was connected
if (pindexFork != pindexNewTip) {
uiInterface.NotifyBlockTip(fInitialDownload, pindexNewTip);
if (!fInitialDownload) { if (!fInitialDownload) {
// Find the hashes of all blocks that weren't previously in the best chain. // Find the hashes of all blocks that weren't previously in the best chain.
std::vector<uint256> vHashes; std::vector<uint256> vHashes;
@ -2636,7 +2640,7 @@ bool ActivateBestChain(CValidationState &state, const CChainParams& chainparams,
// Notify external listeners about the new tip. // Notify external listeners about the new tip.
if (!vHashes.empty()) { if (!vHashes.empty()) {
GetMainSignals().UpdatedBlockTip(pindexNewTip); GetMainSignals().UpdatedBlockTip(pindexNewTip);
uiInterface.NotifyBlockTip(vHashes.front()); }
} }
} }
} while(pindexMostWork != chainActive.Tip()); } while(pindexMostWork != chainActive.Tip());

View file

@ -453,8 +453,8 @@ void BitcoinGUI::setClientModel(ClientModel *clientModel)
setNumConnections(clientModel->getNumConnections()); setNumConnections(clientModel->getNumConnections());
connect(clientModel, SIGNAL(numConnectionsChanged(int)), this, SLOT(setNumConnections(int))); connect(clientModel, SIGNAL(numConnectionsChanged(int)), this, SLOT(setNumConnections(int)));
setNumBlocks(clientModel->getNumBlocks(), clientModel->getLastBlockDate()); setNumBlocks(clientModel->getNumBlocks(), clientModel->getLastBlockDate(), clientModel->getVerificationProgress(NULL));
connect(clientModel, SIGNAL(numBlocksChanged(int,QDateTime)), this, SLOT(setNumBlocks(int,QDateTime))); connect(clientModel, SIGNAL(numBlocksChanged(int,QDateTime,double)), this, SLOT(setNumBlocks(int,QDateTime,double)));
// Receive and report messages from client model // Receive and report messages from client model
connect(clientModel, SIGNAL(message(QString,QString,unsigned int)), this, SLOT(message(QString,QString,unsigned int))); connect(clientModel, SIGNAL(message(QString,QString,unsigned int)), this, SLOT(message(QString,QString,unsigned int)));
@ -682,7 +682,7 @@ void BitcoinGUI::setNumConnections(int count)
labelConnectionsIcon->setToolTip(tr("%n active connection(s) to Bitcoin network", "", count)); labelConnectionsIcon->setToolTip(tr("%n active connection(s) to Bitcoin network", "", count));
} }
void BitcoinGUI::setNumBlocks(int count, const QDateTime& blockDate) void BitcoinGUI::setNumBlocks(int count, const QDateTime& blockDate, double nVerificationProgress)
{ {
if(!clientModel) if(!clientModel)
return; return;
@ -759,7 +759,7 @@ void BitcoinGUI::setNumBlocks(int count, const QDateTime& blockDate)
progressBarLabel->setVisible(true); progressBarLabel->setVisible(true);
progressBar->setFormat(tr("%1 behind").arg(timeBehindText)); progressBar->setFormat(tr("%1 behind").arg(timeBehindText));
progressBar->setMaximum(1000000000); progressBar->setMaximum(1000000000);
progressBar->setValue(clientModel->getVerificationProgress() * 1000000000.0 + 0.5); progressBar->setValue(nVerificationProgress * 1000000000.0 + 0.5);
progressBar->setVisible(true); progressBar->setVisible(true);
tooltip = tr("Catching up...") + QString("<br>") + tooltip; tooltip = tr("Catching up...") + QString("<br>") + tooltip;

View file

@ -150,7 +150,7 @@ public Q_SLOTS:
/** Set number of connections shown in the UI */ /** Set number of connections shown in the UI */
void setNumConnections(int count); void setNumConnections(int count);
/** Set number of blocks and last block date shown in the UI */ /** Set number of blocks and last block date shown in the UI */
void setNumBlocks(int count, const QDateTime& blockDate); void setNumBlocks(int count, const QDateTime& blockDate, double nVerificationProgress);
/** Notify the user of an event from the core network or transaction handling code. /** Notify the user of an event from the core network or transaction handling code.
@param[in] title the message box / notification title @param[in] title the message box / notification title

View file

@ -22,17 +22,16 @@
#include <QDebug> #include <QDebug>
#include <QTimer> #include <QTimer>
class CBlockIndex;
static const int64_t nClientStartupTime = GetTime(); static const int64_t nClientStartupTime = GetTime();
static int64_t nLastBlockTipUpdateNotification = 0;
ClientModel::ClientModel(OptionsModel *optionsModel, QObject *parent) : ClientModel::ClientModel(OptionsModel *optionsModel, QObject *parent) :
QObject(parent), QObject(parent),
optionsModel(optionsModel), optionsModel(optionsModel),
peerTableModel(0), peerTableModel(0),
banTableModel(0), banTableModel(0),
cachedNumBlocks(0),
cachedBlockDate(QDateTime()),
cachedReindexing(0),
cachedImporting(0),
pollTimer(0) pollTimer(0)
{ {
peerTableModel = new PeerTableModel(this); peerTableModel = new PeerTableModel(this);
@ -99,40 +98,21 @@ size_t ClientModel::getMempoolDynamicUsage() const
return mempool.DynamicMemoryUsage(); return mempool.DynamicMemoryUsage();
} }
double ClientModel::getVerificationProgress() const double ClientModel::getVerificationProgress(const CBlockIndex *tipIn) const
{ {
CBlockIndex *tip = const_cast<CBlockIndex *>(tipIn);
if (!tip)
{
LOCK(cs_main); LOCK(cs_main);
return Checkpoints::GuessVerificationProgress(Params().Checkpoints(), chainActive.Tip()); tip = chainActive.Tip();
}
return Checkpoints::GuessVerificationProgress(Params().Checkpoints(), tip);
} }
void ClientModel::updateTimer() void ClientModel::updateTimer()
{ {
// Get required lock upfront. This avoids the GUI from getting stuck on // no locking required at this point
// periodical polls if the core is holding the locks for a longer time - // the following calls will aquire the required lock
// for example, during a wallet rescan.
TRY_LOCK(cs_main, lockMain);
if (!lockMain)
return;
// Some quantities (such as number of blocks) change so fast that we don't want to be notified for each change.
// Periodically check and update with a timer.
int newNumBlocks = getNumBlocks();
QDateTime newBlockDate = getLastBlockDate();
// check for changed number of blocks we have, number of blocks peers claim to have, reindexing state and importing state
if (cachedNumBlocks != newNumBlocks ||
cachedBlockDate != newBlockDate ||
cachedReindexing != fReindex ||
cachedImporting != fImporting)
{
cachedNumBlocks = newNumBlocks;
cachedBlockDate = newBlockDate;
cachedReindexing = fReindex;
cachedImporting = fImporting;
Q_EMIT numBlocksChanged(newNumBlocks, newBlockDate);
}
Q_EMIT mempoolSizeChanged(getMempoolSize(), getMempoolDynamicUsage()); Q_EMIT mempoolSizeChanged(getMempoolSize(), getMempoolDynamicUsage());
Q_EMIT bytesChanged(getTotalBytesRecv(), getTotalBytesSent()); Q_EMIT bytesChanged(getTotalBytesRecv(), getTotalBytesSent());
} }
@ -261,6 +241,23 @@ static void BannedListChanged(ClientModel *clientmodel)
QMetaObject::invokeMethod(clientmodel, "updateBanlist", Qt::QueuedConnection); QMetaObject::invokeMethod(clientmodel, "updateBanlist", Qt::QueuedConnection);
} }
static void BlockTipChanged(ClientModel *clientmodel, bool initialSync, const CBlockIndex *pIndex)
{
// lock free async UI updates in case we have a new block tip
// during initial sync, only update the UI if the last update
// was > 250ms (MODEL_UPDATE_DELAY) ago
int64_t now = 0;
if (initialSync)
now = GetTimeMillis();
// if we are in-sync, update the UI regardless of last update time
if (!initialSync || now - nLastBlockTipUpdateNotification > MODEL_UPDATE_DELAY) {
//pass a async signal to the UI thread
Q_EMIT clientmodel->numBlocksChanged(pIndex->nHeight, QDateTime::fromTime_t(pIndex->GetBlockTime()), clientmodel->getVerificationProgress(pIndex));
nLastBlockTipUpdateNotification = now;
}
}
void ClientModel::subscribeToCoreSignals() void ClientModel::subscribeToCoreSignals()
{ {
// Connect signals to client // Connect signals to client
@ -268,6 +265,7 @@ void ClientModel::subscribeToCoreSignals()
uiInterface.NotifyNumConnectionsChanged.connect(boost::bind(NotifyNumConnectionsChanged, this, _1)); uiInterface.NotifyNumConnectionsChanged.connect(boost::bind(NotifyNumConnectionsChanged, this, _1));
uiInterface.NotifyAlertChanged.connect(boost::bind(NotifyAlertChanged, this, _1, _2)); uiInterface.NotifyAlertChanged.connect(boost::bind(NotifyAlertChanged, this, _1, _2));
uiInterface.BannedListChanged.connect(boost::bind(BannedListChanged, this)); uiInterface.BannedListChanged.connect(boost::bind(BannedListChanged, this));
uiInterface.NotifyBlockTip.connect(boost::bind(BlockTipChanged, this, _1, _2));
} }
void ClientModel::unsubscribeFromCoreSignals() void ClientModel::unsubscribeFromCoreSignals()
@ -277,4 +275,5 @@ void ClientModel::unsubscribeFromCoreSignals()
uiInterface.NotifyNumConnectionsChanged.disconnect(boost::bind(NotifyNumConnectionsChanged, this, _1)); uiInterface.NotifyNumConnectionsChanged.disconnect(boost::bind(NotifyNumConnectionsChanged, this, _1));
uiInterface.NotifyAlertChanged.disconnect(boost::bind(NotifyAlertChanged, this, _1, _2)); uiInterface.NotifyAlertChanged.disconnect(boost::bind(NotifyAlertChanged, this, _1, _2));
uiInterface.BannedListChanged.disconnect(boost::bind(BannedListChanged, this)); uiInterface.BannedListChanged.disconnect(boost::bind(BannedListChanged, this));
uiInterface.NotifyBlockTip.disconnect(boost::bind(BlockTipChanged, this, _1, _2));
} }

View file

@ -15,6 +15,7 @@ class PeerTableModel;
class TransactionTableModel; class TransactionTableModel;
class CWallet; class CWallet;
class CBlockIndex;
QT_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE
class QTimer; class QTimer;
@ -59,7 +60,7 @@ public:
quint64 getTotalBytesRecv() const; quint64 getTotalBytesRecv() const;
quint64 getTotalBytesSent() const; quint64 getTotalBytesSent() const;
double getVerificationProgress() const; double getVerificationProgress(const CBlockIndex *tip) const;
QDateTime getLastBlockDate() const; QDateTime getLastBlockDate() const;
//! Return true if core is doing initial block download //! Return true if core is doing initial block download
@ -81,11 +82,6 @@ private:
PeerTableModel *peerTableModel; PeerTableModel *peerTableModel;
BanTableModel *banTableModel; BanTableModel *banTableModel;
int cachedNumBlocks;
QDateTime cachedBlockDate;
bool cachedReindexing;
bool cachedImporting;
QTimer *pollTimer; QTimer *pollTimer;
void subscribeToCoreSignals(); void subscribeToCoreSignals();
@ -93,7 +89,7 @@ private:
Q_SIGNALS: Q_SIGNALS:
void numConnectionsChanged(int count); void numConnectionsChanged(int count);
void numBlocksChanged(int count, const QDateTime& blockDate); void numBlocksChanged(int count, const QDateTime& blockDate, double nVerificationProgress);
void mempoolSizeChanged(long count, size_t mempoolSizeInBytes); void mempoolSizeChanged(long count, size_t mempoolSizeInBytes);
void alertsChanged(const QString &warnings); void alertsChanged(const QString &warnings);
void bytesChanged(quint64 totalBytesIn, quint64 totalBytesOut); void bytesChanged(quint64 totalBytesIn, quint64 totalBytesOut);

View file

@ -343,8 +343,8 @@ void RPCConsole::setClientModel(ClientModel *model)
setNumConnections(model->getNumConnections()); setNumConnections(model->getNumConnections());
connect(model, SIGNAL(numConnectionsChanged(int)), this, SLOT(setNumConnections(int))); connect(model, SIGNAL(numConnectionsChanged(int)), this, SLOT(setNumConnections(int)));
setNumBlocks(model->getNumBlocks(), model->getLastBlockDate()); setNumBlocks(model->getNumBlocks(), model->getLastBlockDate(), model->getVerificationProgress(NULL));
connect(model, SIGNAL(numBlocksChanged(int,QDateTime)), this, SLOT(setNumBlocks(int,QDateTime))); connect(model, SIGNAL(numBlocksChanged(int,QDateTime,double)), this, SLOT(setNumBlocks(int,QDateTime,double)));
updateTrafficStats(model->getTotalBytesRecv(), model->getTotalBytesSent()); updateTrafficStats(model->getTotalBytesRecv(), model->getTotalBytesSent());
connect(model, SIGNAL(bytesChanged(quint64,quint64)), this, SLOT(updateTrafficStats(quint64, quint64))); connect(model, SIGNAL(bytesChanged(quint64,quint64)), this, SLOT(updateTrafficStats(quint64, quint64)));
@ -525,7 +525,7 @@ void RPCConsole::setNumConnections(int count)
ui->numberOfConnections->setText(connections); ui->numberOfConnections->setText(connections);
} }
void RPCConsole::setNumBlocks(int count, const QDateTime& blockDate) void RPCConsole::setNumBlocks(int count, const QDateTime& blockDate, double nVerificationProgress)
{ {
ui->numberOfBlocks->setText(QString::number(count)); ui->numberOfBlocks->setText(QString::number(count));
ui->lastBlockTime->setText(blockDate.toString()); ui->lastBlockTime->setText(blockDate.toString());

View file

@ -83,7 +83,7 @@ public Q_SLOTS:
/** Set number of connections shown in the UI */ /** Set number of connections shown in the UI */
void setNumConnections(int count); void setNumConnections(int count);
/** Set number of blocks and last block date shown in the UI */ /** Set number of blocks and last block date shown in the UI */
void setNumBlocks(int count, const QDateTime& blockDate); void setNumBlocks(int count, const QDateTime& blockDate, double nVerificationProgress);
/** Set size (number of transactions and memory usage) of the mempool in the UI */ /** Set size (number of transactions and memory usage) of the mempool in the UI */
void setMempoolSize(long numberOfTxs, size_t dynUsage); void setMempoolSize(long numberOfTxs, size_t dynUsage);
/** Go forward or back in history */ /** Go forward or back in history */

View file

@ -124,7 +124,7 @@ void SendCoinsDialog::setClientModel(ClientModel *clientModel)
this->clientModel = clientModel; this->clientModel = clientModel;
if (clientModel) { if (clientModel) {
connect(clientModel, SIGNAL(numBlocksChanged(int,QDateTime)), this, SLOT(updateSmartFeeLabel())); connect(clientModel, SIGNAL(numBlocksChanged(int,QDateTime,double)), this, SLOT(updateSmartFeeLabel()));
} }
} }

View file

@ -15,6 +15,7 @@
class CBasicKeyStore; class CBasicKeyStore;
class CWallet; class CWallet;
class uint256; class uint256;
class CBlockIndex;
/** General change type (added, updated, removed). */ /** General change type (added, updated, removed). */
enum ChangeType enum ChangeType
@ -94,7 +95,7 @@ public:
boost::signals2::signal<void (const std::string &title, int nProgress)> ShowProgress; boost::signals2::signal<void (const std::string &title, int nProgress)> ShowProgress;
/** New block has been accepted */ /** New block has been accepted */
boost::signals2::signal<void (const uint256& hash)> NotifyBlockTip; boost::signals2::signal<void (bool, const CBlockIndex *)> NotifyBlockTip;
/** Banlist did change. */ /** Banlist did change. */
boost::signals2::signal<void (void)> BannedListChanged; boost::signals2::signal<void (void)> BannedListChanged;