Skip to content
This repository has been archived by the owner on Sep 26, 2019. It is now read-only.

Pipeline chain download - Checkpoints #1203

Merged
merged 24 commits into from
Apr 2, 2019

Conversation

ajsutton
Copy link
Contributor

@ajsutton ajsutton commented Apr 2, 2019

PR description

Implement an Iterator that retrieves checkpoint headers and creates ranges based on those to act as the start of the chain download pipeline.

Also adds the plumbing required to hook the pipeline download into Pantheon, but currently toggled off (it only gets as far as creating checkpoint ranges currently).

Builds on #1196.

ajsutton and others added 18 commits April 1, 2019 08:51
…astSynchronizer and FullSynchronizer to FastDownloaderFactory and FullDownloaderFactory.
…wnloaderFactory to FullSyncDownloader since it doesn't actually need a factory.
…pleted (SyncTargetManager would just blindly re-use it).
…nd wire them into FastSyncChainDownloader with a currently off feature toggle.
Copy link
Contributor

@mbaxter mbaxter left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A few questions / comments, but looks good for the most part!

final BlockHeader commonAncestor,
final int checkpointTimeoutsPermitted,
final int newHeaderWaitDuration,
final TimeUnit newHeaderWaitDurationUnit) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(optional) You could simplify the constructor by accepting a single Duration object rather than newHeaderWaitDuration and newHeaderWaitDurationUnit.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

True, we can't pass it on as a duration to the get call that needs it but no need to share that pain.

if (pendingCheckpointsRequest.isPresent()) {
return getCheckpointRangeFromPendingRequest();
}
pendingCheckpointsRequest =
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need any kind of throttling here? To slow down requests if we keep sending and failing in quick succession?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Probably a good thing to do.

final SynchronizerConfiguration syncConfig,
final ProtocolSchedule<?> protocolSchedule,
final EthContext ethContext,
final UnaryOperator<List<BlockHeader>> checkpointFilter,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(optional) You could set this as a Supplier<OptionalLong> that provides the max block number to request, then we can avoid going over the limit for the last fast sync request.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm going to leave this for now but have a note to revisit. We need to ensure the last checkpoint header for fast sync is the pivot block and it sometimes needs to be explicitly inserted. We could use an Optional<BlockHeader> finalCheckpoint and include all the logic inside CheckpointHeaderFetcher but then it winds up with a bunch of fast sync specific logic mixed in. Need to play around with it but want to get something actually working first.


@Override
public CompletableFuture<Void> start() {
return performDownload();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You may want to use an AtomicBoolean to make sure start is only called once.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We do tend to follow that pattern. Done.

}

@Override
public synchronized void cancel() {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do you need these synchronized keywords? If you only allow cancellation once, after starting (if(started.get() && cancelled.compareAndSet(false, true)){...}), do you need to synchronize?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We need the synchronised keyword to protect access to the currentDownloadPipeline field and to ensure that when we're cancelling, there isn't another thread starting a different pipeline. We need the creation, starting and assignment to currentDownloadPipeline to be a single atomic operation so we know cancel cancels the pipeline that's actually running.

@ajsutton ajsutton merged commit e66f325 into PegaSysEng:master Apr 2, 2019
@ajsutton ajsutton deleted the pipeline-download-checkpoints branch April 2, 2019 22:37
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants