diff --git a/alethzero/DownloadView.cpp b/alethzero/DownloadView.cpp
index 210649edb..5112f961c 100644
--- a/alethzero/DownloadView.cpp
+++ b/alethzero/DownloadView.cpp
@@ -30,29 +30,95 @@ using namespace std;
using namespace dev;
using namespace dev::eth;
-DownloadView::DownloadView(QWidget* _p): QWidget(_p)
+SyncView::SyncView(QWidget* _p): QWidget(_p)
{
}
-void DownloadView::paintEvent(QPaintEvent*)
+void SyncView::paintEvent(QPaintEvent*)
{
QPainter p(this);
-
p.fillRect(rect(), Qt::white);
- if (!m_man || m_man->chainEmpty() || !m_man->subCount())
+
+ if (!m_client)
+ return;
+
+ DownloadMan const* man = m_client->downloadMan();
+ BlockQueueStatus bqs = m_client->blockQueueStatus();
+ SyncStatus sync = m_client->syncStatus();
+
+ unsigned syncFrom = m_client->numberFromHash(PendingBlockHash);
+ unsigned syncImported = syncFrom;
+ unsigned syncImporting = syncImported + bqs.importing;
+ unsigned syncVerified = syncImporting + bqs.verified;
+ unsigned syncVerifying = syncVerified + bqs.verifying;
+ unsigned syncUnverified = syncVerifying + bqs.unverified;
+ unsigned syncUnknown = syncUnverified + bqs.unknown;
+
+ // best effort guess. assumes there's no forks.
+ unsigned downloadFrom = m_client->numberFromHash(m_client->isKnown(man->firstBlock()) ? man->firstBlock() : PendingBlockHash);
+ unsigned downloadCount = sync.blocksTotal;
+ DownloadMan::Overview overview = man->overview();
+ unsigned downloadDone = downloadFrom + overview.total;
+ unsigned downloadFlank = downloadFrom + overview.firstIncomplete;
+ unsigned downloadPoint = downloadFrom + overview.lastComplete;
+
+ unsigned hashFrom = sync.state == SyncState::Hashes ? m_client->numberFromHash(PendingBlockHash) : downloadFrom;
+ unsigned hashCount = sync.state == SyncState::Hashes ? sync.hashesTotal : downloadCount;
+ unsigned hashDone = hashFrom + (sync.state == SyncState::Hashes ? sync.hashesReceived : hashCount);
+
+ m_lastFrom = min(syncFrom, m_lastFrom);
+ unsigned from = min(min(hashFrom, downloadFrom), min(syncFrom, m_lastFrom));
+ unsigned count = max(hashFrom + hashCount, downloadFrom + downloadCount) - from;
+ m_lastFrom = (m_lastFrom * 95 + syncFrom) / 100;
+
+ if (!count)
+ {
+ m_lastFrom = (unsigned)-1;
return;
+ }
+
+ cnote << "Range " << from << "-" << (from + count);
+ auto r = [&](unsigned u) {
+ return toString((u - from) * 100 / count) + "%";
+ };
+
+ if (count)
+ {
+ cnote << "Hashes:" << r(hashDone) << " Blocks:" << r(downloadFlank) << r(downloadDone) << r(downloadPoint);
+ cnote << "Importing:" << r(syncFrom) << r(syncImported) << r(syncImporting) << r(syncVerified) << r(syncVerifying) << r(syncUnverified) << r(syncUnknown);
+ }
+
+ if (!man || man->chainEmpty() || !man->subCount())
+ return;
+
+ float s = min(rect().width(), rect().height());
+ QPen pen;
+ pen.setCapStyle(Qt::FlatCap);
+ pen.setWidthF(s / 10);
+ p.setPen(pen);
+ auto middle = [&](float x) {
+ return QRectF(s / 2 - s / 2 * x, 0 + s / 2 - s / 2 * x, s * x, s * x);
+ };
+
+ auto toArc = [&](unsigned x) {
+ return (x - from) * -5760.f / count;
+ };
+ const float arcFrom = 90 * 16.f;
+ p.drawArc(middle(0.5f), arcFrom, toArc(downloadDone));
+ p.drawPie(middle(0.2f), arcFrom, toArc(hashDone));
+ return;
double ratio = (double)rect().width() / rect().height();
if (ratio < 1)
ratio = 1 / ratio;
- double n = min(16.0, min(rect().width(), rect().height()) / ceil(sqrt(m_man->chainSize() / ratio)));
+ double n = min(16.0, min(rect().width(), rect().height()) / ceil(sqrt(man->chainSize() / ratio)));
// QSizeF area(rect().width() / floor(rect().width() / n), rect().height() / floor(rect().height() / n));
QSizeF area(n, n);
QPointF pos(0, 0);
- auto bg = m_man->blocksGot();
- unsigned subCount = m_man->subCount();
+ auto bg = man->blocksGot();
+ unsigned subCount = man->subCount();
if (subCount == 0)
return;
unsigned dh = 360 / subCount;
@@ -64,7 +130,7 @@ void DownloadView::paintEvent(QPaintEvent*)
else
{
unsigned h = 0;
- m_man->foreachSub([&](DownloadSub const& sub)
+ man->foreachSub([&](DownloadSub const& sub)
{
if (sub.askedContains(i))
s = h;
diff --git a/alethzero/DownloadView.h b/alethzero/DownloadView.h
index d0fc445f8..9ee2428b2 100644
--- a/alethzero/DownloadView.h
+++ b/alethzero/DownloadView.h
@@ -32,21 +32,23 @@
#endif
namespace dev { namespace eth {
-class DownloadMan;
+class Client;
}}
-class DownloadView: public QWidget
+class SyncView: public QWidget
{
Q_OBJECT
public:
- DownloadView(QWidget* _p = nullptr);
+ SyncView(QWidget* _p = nullptr);
- void setDownloadMan(dev::eth::DownloadMan const* _man) { m_man = _man; }
+ void setEthereum(dev::eth::Client const* _c) { m_client = _c; }
protected:
virtual void paintEvent(QPaintEvent*);
private:
- dev::eth::DownloadMan const* m_man = nullptr;
+ dev::eth::Client const* m_client = nullptr;
+
+ unsigned m_lastFrom = (unsigned)-1;
};
diff --git a/alethzero/Main.ui b/alethzero/Main.ui
index b2e3a9a29..37ff7f66c 100644
--- a/alethzero/Main.ui
+++ b/alethzero/Main.ui
@@ -1149,7 +1149,7 @@ font-size: 14pt
0
-
-
+
@@ -1814,7 +1814,7 @@ font-size: 14pt
1
- DownloadView
+ SyncView
QWidget
1
diff --git a/alethzero/MainWin.cpp b/alethzero/MainWin.cpp
index bc569c5cf..ba4bec863 100644
--- a/alethzero/MainWin.cpp
+++ b/alethzero/MainWin.cpp
@@ -1993,12 +1993,12 @@ void Main::on_net_triggered()
web3()->setNetworkPreferences(netPrefs(), ui->dropPeers->isChecked());
ethereum()->setNetworkId(m_privateChain.size() ? sha3(m_privateChain.toStdString()) : h256());
web3()->startNetwork();
- ui->downloadView->setDownloadMan(ethereum()->downloadMan());
+ ui->downloadView->setEthereum(ethereum());
ui->enode->setText(QString::fromStdString(web3()->enode()));
}
else
{
- ui->downloadView->setDownloadMan(nullptr);
+ ui->downloadView->setEthereum(nullptr);
writeSettings();
web3()->stopNetwork();
}
diff --git a/exp/main.cpp b/exp/main.cpp
index 1db9b4267..88608f8cf 100644
--- a/exp/main.cpp
+++ b/exp/main.cpp
@@ -135,7 +135,7 @@ int main()
DownloadSub s0(man);
DownloadSub s1(man);
DownloadSub s2(man);
- man.resetToChain(h256s({u256(0), u256(1), u256(2), u256(3), u256(4), u256(5), u256(6), u256(7), u256(8)}));
+ man.resetToChain(h256s({u256(0), u256(1), u256(2), u256(3), u256(4), u256(5), u256(6), u256(7), u256(8)}), 0);
assert((s0.nextFetch(2) == h256Set{(u256)7, (u256)8}));
assert((s1.nextFetch(2) == h256Set{(u256)5, (u256)6}));
assert((s2.nextFetch(2) == h256Set{(u256)3, (u256)4}));
diff --git a/libdevcore/RangeMask.h b/libdevcore/RangeMask.h
index eccc8305d..6c32517f5 100644
--- a/libdevcore/RangeMask.h
+++ b/libdevcore/RangeMask.h
@@ -200,6 +200,20 @@ public:
return c;
}
+ size_t firstOut() const
+ {
+ if (m_ranges.empty() || !m_ranges.count(m_all.first))
+ return m_all.first;
+ return m_ranges.at(m_all.first);
+ }
+
+ size_t lastIn() const
+ {
+ if (m_ranges.empty())
+ return m_all.first;
+ return m_ranges.rbegin()->second - 1;
+ }
+
private:
/// The ground range.
UnsignedRange m_all;
diff --git a/libethereum/BlockChainSync.cpp b/libethereum/BlockChainSync.cpp
index e22f10880..5dd1a97cb 100644
--- a/libethereum/BlockChainSync.cpp
+++ b/libethereum/BlockChainSync.cpp
@@ -80,7 +80,7 @@ DownloadMan& BlockChainSync::downloadMan()
void BlockChainSync::abortSync()
{
- downloadMan().resetToChain(h256s());
+ downloadMan().reset();
}
void BlockChainSync::onPeerStatus(std::shared_ptr _peer)
diff --git a/libethereum/DownloadMan.cpp b/libethereum/DownloadMan.cpp
index 5e68e3c49..a9d353292 100644
--- a/libethereum/DownloadMan.cpp
+++ b/libethereum/DownloadMan.cpp
@@ -24,6 +24,16 @@ using namespace std;
using namespace dev;
using namespace dev::eth;
+DownloadMan::Overview DownloadMan::overview() const
+{
+ ReadGuard l(m_lock);
+ Overview ret;
+ ret.firstIncomplete = m_blocksGot.firstOut();
+ ret.lastComplete = ret.lastStarted = m_blocksGot.lastIn();// TODO: lastStarted properly
+ ret.total = m_blocksGot.size();
+ return ret;
+}
+
DownloadSub::DownloadSub(DownloadMan& _man): m_man(&_man)
{
WriteGuard l(m_man->x_subs);
diff --git a/libethereum/DownloadMan.h b/libethereum/DownloadMan.h
index ac99e1d36..b697d87ae 100644
--- a/libethereum/DownloadMan.h
+++ b/libethereum/DownloadMan.h
@@ -82,6 +82,14 @@ class DownloadMan
friend class DownloadSub;
public:
+ struct Overview
+ {
+ size_t total;
+ size_t firstIncomplete;
+ size_t lastComplete;
+ size_t lastStarted;
+ };
+
~DownloadMan()
{
for (auto i: m_subs)
@@ -97,11 +105,9 @@ public:
void resetToChain(h256s const& _chain)
{
- {
- ReadGuard l(x_subs);
+ DEV_READ_GUARDED(x_subs)
for (auto i: m_subs)
i->resetFetch();
- }
WriteGuard l(m_lock);
m_chain.clear();
m_chain.reserve(_chain.size());
@@ -112,11 +118,9 @@ public:
void reset()
{
- {
- ReadGuard l(x_subs);
+ DEV_READ_GUARDED(x_subs)
for (auto i: m_subs)
i->resetFetch();
- }
WriteGuard l(m_lock);
m_chain.clear();
m_blocksGot.reset();
@@ -127,11 +131,9 @@ public:
ReadGuard l(m_lock);
auto ret = m_blocksGot;
if (!_desperate)
- {
- ReadGuard l(x_subs);
- for (auto i: m_subs)
- ret += i->m_asked;
- }
+ DEV_READ_GUARDED(x_subs)
+ for (auto i: m_subs)
+ ret += i->m_asked;
return ret;
}
@@ -144,12 +146,15 @@ public:
h256s remaining() const
{
h256s ret;
- ReadGuard l(m_lock);
- for (auto i: m_blocksGot.inverted())
- ret.push_back(m_chain[i]);
+ DEV_READ_GUARDED(m_lock)
+ for (auto i: m_blocksGot.inverted())
+ ret.push_back(m_chain[i]);
return ret;
}
+ h256 firstBlock() const { return m_chain.empty() ? h256() : m_chain[0]; }
+ Overview overview() const;
+
size_t chainSize() const { ReadGuard l(m_lock); return m_chain.size(); }
size_t chainEmpty() const { ReadGuard l(m_lock); return m_chain.empty(); }
void foreachSub(std::function const& _f) const { ReadGuard l(x_subs); for(auto i: m_subs) _f(*i); }