This, almost UI only change, will add a Pause/Resume button to the modal overlay to pause/resume block downloads during IBD.
This is an effective way to pause/resume IBD during a time when the computers resources are required somewhere else.
This, almost UI only change, will add a Pause/Resume button to the modal overlay to pause/resume block downloads during IBD.
This is an effective way to pause/resume IBD during a time when the computers resources are required somewhere else.
I extracted this from my SPV branch. Especially there, it is very useful to pause IBD and continue with SPV during a time where you don’t want to use all available resources on verification.
But also without SPV, I think this can be useful (pause IBD and not loose broadcast capabilities, fetch headers but not the blocks)…
Isn’t network toggle button usable in this case? If it is not, let’s fix it instead…
Imo those are different features, but I agree that the GUI should not “diverge” in regard to presenting features. The toggle network functionality should be removed from the network icon and a proper button should be put beside the new “Pause” button?
Isn’t network toggle button usable in this case? If it is not, let’s fix it instead…
Imo those are different features, but I agree that the GUI should not “diverge” in regard to presenting features. The toggle network functionality should be removed from the network icon and a proper button should be put beside the new “Pause” button?
Yes. These are internally two completely different features. Expose to the users, these have similar effects.
The “Pause” button won’t be visible in normal cases.
Yes. The modal overlay is currently only accessible during IBD. Though, we could extend it to support a state where the chain is in-sync and show it when someone click on the network statusbar icon.
13@@ -14,6 +14,10 @@ void RegisterNodeSignals(CNodeSignals& nodeSignals);
14 /** Unregister a network node */
15 void UnregisterNodeSignals(CNodeSignals& nodeSignals);
16
17+/** if disabled, blocks will not be requested automatically, usefull for low-resources-available mode */
80@@ -81,6 +81,10 @@ class ClientModel : public QObject
81 QString formatClientStartupTime() const;
82 QString dataDir() const;
83
84+ // get/set state about autorequesting-blocks during IBD
85+ bool isAutorequestBlocks() const;
isAutorequestingBlocks
(add ing
). The setAutorequestBlocks
below is fine as is, though.
22@@ -23,6 +23,10 @@ void RegisterNodeSignals(CNodeSignals& nodeSignals);
23 /** Unregister a network node */
24 void UnregisterNodeSignals(CNodeSignals& nodeSignals);
25
26+/** if disabled, blocks will not be requested automatically, usefull for low-resources-available mode */
27+static const bool DEFAULT_AUTOMATIC_BLOCK_REQUESTS = true;
28+extern std::atomic<bool> fAutoRequestBlocks;
SetAutoRequestBlocks(bool)
GetAutoRequestBlocks()
233@@ -233,6 +234,22 @@ QString ClientModel::dataDir() const
234 return GUIUtil::boostPathToQString(GetDataDir());
235 }
236
237+bool ClientModel::isAutorequestBlocks() const
FindNextBlocksToDownload
is called; is that good enough? I suppose it is, because SendMessages
is called periodically (every 100 ms?).
Overhauled the PR and addresses @laanwj points.
Also, I added the info “Blocks requested from peers” (blocks in flight). This may be important because pause will not result in disconnecting peers. Already requested blocks will be downloaded (and verified) in the “pause” state.
If blocks are in flight and the pause has been triggered, there is now a special info label Wait to finish current downloads
.
Well, I have to change my previous opinion. I think this can be useful.
Concept ACK
Will test soon.
ACK e952b67d294043d9758b37bf2be57a982b41c051
Code looks good. On the UI feature, two minor comments:
Testing this again.
ACK https://github.com/bitcoin/bitcoin/pull/9502/commits/fc84323d8ee447f1461a10b7f3b29d113f9f4a43
I think this could be even more usable if it can be called once fully in sync with the network. But I can’t display the overlay then…
I think this could be even more usable if it can be called once fully in sync with the network. But I can’t display the overlay then…
Hm I vaguely remember I added that functionality once, you should be able to bring up the overlay by the secret trick of clicking on the sync icon.
I think this could be even more usable if it can be called once fully in sync with the network. But I can’t display the overlay then…
There are four ways how the modal-overlay can be opened: -> auto-opens when in IBD/sync -> Click on the warning icons next to the balance -> Click on the progress bar during IBD/sync -> Click on the sync icon in the status bar
Though I agree with you, there is no option how to open it once you are in sync… which could be useful, but independent to this PR.
@paveljanik Oh, though it also worked with the checkmark that takes its place.
Yes. We should probably allow that.
Concept ACK. (I haven’t reviewed the qt code at all, but I did look over the net_processing changes.)
What is the intended behavior if the user turns off block download after being synced or nearly synced? I believe this PR only disables the parallel fetch logic, and not the direct fetch – so block download could conceivably be disabled by the user, but blocks could still be requested as they are announced. (Maybe this is hard to accomplish, if the modal overlay is not accessible when bitcoind is close to synced, but my recollection is that the modal overlay becomes visible whenever the headers chain is out of sync, which can happen even after leaving IBD, does that sound right?)
Perhaps the ability to disable block download should disappear if we’re close to caught up, eg if CanDirectFetch()
is true?
Additionally, perhaps if we’ve disabled block download, we should also disable transaction download.
Rebased and addressed the CanDirectFetch()
issue @sdaftuar mentioned.
The current implementation avoids exposing net_processing.cpp
’s CanDirectFetch()
for the reasons a) it does always use chainActive (lock) and b) to avoid another core-layer dependency.
I’m not doing to tackle the transaction download in the PR (main scope is disabling block download).
ACK
I have tested this on a node that was a few weeks behind and I was able to pause the block download multiple times while it was syncing. I noticed that even when paused, UpdateTip is still happening for hundreds of blocks after what the GUI said still needed to be downloaded. I assume this is because it still processes all of the blocks that have been downloaded and the downloading happens faster than the processing. The UpdateTip lines do stop after a while which I assume is because all downloaded blocks have been processed.
I assume this is because it still processes all of the blocks that have been downloaded and the downloading happens faster than the processing.
Yes, that’s expected. We download multiple blocks in parallel, ahead of the next one to connect. I expect that this PR also keeps processing the ones that were in flight at the time blocks downloads are disabled.
353@@ -334,6 +354,33 @@ QLabel { color: rgb(40,40,40); }</string>
354 <number>10</number>
355 </property>
356 <item>
357+ <widget class="QPushButton" name="pauseResumeVerification">
toggleDownloadButton
.
353@@ -334,6 +354,33 @@ QLabel { color: rgb(40,40,40); }</string>
354 <number>10</number>
355 </property>
356 <item>
leftMargin
above to be consistent.
203+
204+void ModalOverlay::updatePauseState(bool pauseActive)
205+{
206+ ui->labelNumberBlocksRequested->setText((pauseActive ? "Finish downloading blocks": "Blocks requested from peers"));
207+ ui->pauseResumeVerification->setText((pauseActive ? "Resume downloading blocks ": "Pause downloading blocks"));
208+ ui->infoLabel->setText((pauseActive && getAmountOfBlocksInFlight() > 0 ? "Wait to finish current downloads...": ""));
nBlocksInFlight
doesn’t always decrease to zero.
nBlocksInFlight > 0
we need to expect network traffic and therefor should still remind the user with the "Wait to finish current..."
.
201+ updatePauseState(pauseActive);
202+}
203+
204+void ModalOverlay::updatePauseState(bool pauseActive)
205+{
206+ ui->labelNumberBlocksRequested->setText((pauseActive ? "Finish downloading blocks": "Blocks requested from peers"));
Downloading: %d blocks
?
3318+
3319+bool isAutoRequestingBlocks() {
3320+ return fAutoRequestBlocks;
3321+}
3322+
3323+unsigned int getAmountOfBlocksInFlight() {
SetAuto
vs isAuto
/getAmount
) for consistency.
63@@ -61,4 +64,10 @@ bool GetNodeStateStats(NodeId nodeid, CNodeStateStats &stats);
64 /** Increase a node's misbehavior score. */
65 void Misbehaving(NodeId nodeid, int howmuch);
66
67+void SetAutoRequestBlocks(bool);
68+bool isAutoRequestingBlocks();
69+
70+/** retruns the amount of blocks in flight (in total) */
137+ // show already requested blocks (in total)
138+ ui->numberBlocksRequested->setText(QString::number(getAmountOfBlocksInFlight()));
139+ eventuallyShowHeaderSyncing(count);
140+ updatePauseState(verificationPauseActive);
141+
142+ // disable pause button when we we can fetch directly
139+ eventuallyShowHeaderSyncing(count);
140+ updatePauseState(verificationPauseActive);
141+
142+ // disable pause button when we we can fetch directly
143+ // avoid using the core-layer's existing CanFetchDirectly()
144+ bool canFetchDirecly = (blockDate.toTime_t() > GetAdjustedTime() - Params().GetConsensus().nPowTargetSpacing * 20);
canFetchDirecly
, should be Directly
203+ updatePauseState(pauseActive);
204+}
205+
206+void ModalOverlay::updatePauseState(bool pauseActive)
207+{
208+ ui->labelNumberBlocksRequested->setText((pauseActive ? "Finish downloading blocks": "Blocks requested from peers"));
:
(same on next two lines)
204+}
205+
206+void ModalOverlay::updatePauseState(bool pauseActive)
207+{
208+ ui->labelNumberBlocksRequested->setText((pauseActive ? "Finish downloading blocks": "Blocks requested from peers"));
209+ ui->pauseResumeVerification->setText((pauseActive ? "Resume downloading blocks ": "Pause downloading blocks"));
:
utACK https://github.com/bitcoin/bitcoin/pull/9502/commits/1375063565a257057707379588b02a8aa44b7bcc
Just a couple of formatting nits inline
3661+bool isAutoRequestingBlocks()
3662+{
3663+ return fAutoRequestBlocks;
3664+}
3665+
3666+unsigned int getAmountOfBlocksInFlight() {
Had a quick test of this (b0a9b8d6dae2a9efcdbc3607b235c37e1f7db31d) on top of master (9b8b1079ddab64ac955766536c38d23dc57bc499). macOS 10.13.3 and Qt 5.10.1.
This is what the overlay model looks like now with this PR (b0a9b8d6dae2a9efcdbc3607b235c37e1f7db31d):
One thing I noticed is after hitting “Pause”, it can take a while to stop downloading blocks. i.e In the images below, we hit pause with 127 blocks “requested from peers” and 145022 total blocks left. However we don’t appear to stop downloading blocks until we’ve reached 144601 total blocks left to download, > 400 blocks later. This could be confusing, and might appear worse on slower connections?
I’ll comment inline about simplifying the new strings.
203+ updatePauseState(pauseActive);
204+}
205+
206+void ModalOverlay::updatePauseState(bool pauseActive)
207+{
208+ ui->labelNumberBlocksRequested->setText((pauseActive ? "Finish downloading blocks" : "Blocks requested from peers"));
205+
206+void ModalOverlay::updatePauseState(bool pauseActive)
207+{
208+ ui->labelNumberBlocksRequested->setText((pauseActive ? "Finish downloading blocks" : "Blocks requested from peers"));
209+ ui->pauseResumeVerification->setText((pauseActive ? "Resume downloading blocks " : "Pause downloading blocks"));
210+ ui->infoLabel->setText((pauseActive && getAmountOfBlocksInFlight() > 0 ? "Wait to finish current downloads..." : ""));
One thing I noticed is after hitting “Pause”, it can take a while to stop downloading blocks. i.e In the images below, we hit pause with 127 blocks “requested from peers” and 145022 total blocks left. However we don’t appear to stop downloading blocks until we’ve reached 144601 total blocks left to download, > 400 blocks later. This could be confusing, and might appear worse on slower connections?
Yes. That could be confusing,.. though I guess there is an explanation. You may still have blocks on your disk that hasn’t been verified due to a missing the next blocks after your tip. This means it is possible to jump a couple of block after downloading a single block.
Also,… we don’t want to ignore the request because the peer is sending it anyway (once requested) and we don’t want to disconnect peers (that feature is already available).
It would be possible to hide that information from the user, though I think it makes more sense to display it so its clear that the “pause” means not “disconnect”.
492@@ -493,6 +493,10 @@ void BitcoinGUI::setClientModel(ClientModel *_clientModel)
493 connect(_clientModel, SIGNAL(networkActiveChanged(bool)), this, SLOT(setNetworkActive(bool)));
494
495 modalOverlay->setKnownBestHeight(_clientModel->getHeaderTipHeight(), QDateTime::fromTime_t(_clientModel->getHeaderTipTime()));
496+ modalOverlay->setPauseResumeState(!_clientModel->isAutoRequestingBlocks());
497+ connect(modalOverlay, SIGNAL(requestVerificationPauseOrResume()), _clientModel, SLOT(toggleAutoRequestBlocks()));
498+ connect(_clientModel, SIGNAL(verificationProgressPauseStateHasChanged(bool)), modalOverlay, SLOT(setPauseResumeState(bool)));
139+ eventuallyShowHeaderSyncing(count);
140+ updatePauseState(verificationPauseActive);
141+
142+ // disable pause button when we can fetch directly
143+ // avoid using the core-layer's existing CanFetchDirectly()
144+ bool canFetchDirectly = (blockDate.toTime_t() > GetAdjustedTime() - Params().GetConsensus().nPowTargetSpacing * 20);