-
Notifications
You must be signed in to change notification settings - Fork 879
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[NC-1508] Added iBFT 2.0 BlockTimerExpiry Event and realated timer ma…
…nagement class (#58) Signed-off-by: Adrian Sutton <adrian.sutton@consensys.net>
- Loading branch information
1 parent
89e860f
commit 6507f03
Showing
4 changed files
with
401 additions
and
1 deletion.
There are no files selected for viewing
94 changes: 94 additions & 0 deletions
94
consensus/ibft/src/main/java/tech/pegasys/pantheon/consensus/ibft/BlockTimer.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,94 @@ | ||
/* | ||
* Copyright 2018 ConsenSys AG. | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with | ||
* the License. You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on | ||
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the | ||
* specific language governing permissions and limitations under the License. | ||
*/ | ||
package tech.pegasys.pantheon.consensus.ibft; | ||
|
||
import tech.pegasys.pantheon.consensus.ibft.ibftevent.BlockTimerExpiry; | ||
import tech.pegasys.pantheon.ethereum.core.BlockHeader; | ||
import tech.pegasys.pantheon.util.time.Clock; | ||
|
||
import java.util.Optional; | ||
import java.util.concurrent.ScheduledExecutorService; | ||
import java.util.concurrent.ScheduledFuture; | ||
import java.util.concurrent.TimeUnit; | ||
|
||
/** Class for starting and keeping organised block timers */ | ||
public class BlockTimer { | ||
private final ScheduledExecutorService timerExecutor; | ||
private Optional<ScheduledFuture<?>> currentTimerTask; | ||
private final IbftEventQueue queue; | ||
private final long minimumTimeBetweenBlocksMillis; | ||
private final Clock clock; | ||
|
||
/** | ||
* Construct a BlockTimer with primed executor service ready to start timers | ||
* | ||
* @param queue The queue in which to put block expiry events | ||
* @param minimumTimeBetweenBlocksMillis Minimum timestamp difference between blocks | ||
* @param timerExecutor Executor service that timers can be scheduled with | ||
* @param clock System clock | ||
*/ | ||
public BlockTimer( | ||
final IbftEventQueue queue, | ||
final long minimumTimeBetweenBlocksMillis, | ||
final ScheduledExecutorService timerExecutor, | ||
final Clock clock) { | ||
this.queue = queue; | ||
this.timerExecutor = timerExecutor; | ||
this.currentTimerTask = Optional.empty(); | ||
this.minimumTimeBetweenBlocksMillis = minimumTimeBetweenBlocksMillis; | ||
this.clock = clock; | ||
} | ||
|
||
/** Cancels the current running round timer if there is one */ | ||
public synchronized void cancelTimer() { | ||
currentTimerTask.ifPresent(t -> t.cancel(false)); | ||
currentTimerTask = Optional.empty(); | ||
} | ||
|
||
/** | ||
* Whether there is a timer currently running or not | ||
* | ||
* @return boolean of whether a timer is ticking or not | ||
*/ | ||
public synchronized boolean isRunning() { | ||
return currentTimerTask.map(t -> !t.isDone()).orElse(false); | ||
} | ||
|
||
/** | ||
* Starts a timer for the supplied round cancelling any previously active block timer | ||
* | ||
* @param round The round identifier which this timer is tracking | ||
* @param chainHeadHeader The header of the chain head | ||
*/ | ||
public synchronized void startTimer( | ||
final ConsensusRoundIdentifier round, final BlockHeader chainHeadHeader) { | ||
cancelTimer(); | ||
|
||
final long now = clock.millisecondsSinceEpoch(); | ||
|
||
// absolute time when the timer is supposed to expire | ||
final long expiryTime = chainHeadHeader.getTimestamp() * 1_000 + minimumTimeBetweenBlocksMillis; | ||
|
||
if (expiryTime > now) { | ||
final long delay = expiryTime - now; | ||
|
||
final Runnable newTimerRunnable = () -> queue.add(new BlockTimerExpiry(round)); | ||
|
||
final ScheduledFuture<?> newTimerTask = | ||
timerExecutor.schedule(newTimerRunnable, delay, TimeUnit.MILLISECONDS); | ||
currentTimerTask = Optional.of(newTimerTask); | ||
} else { | ||
queue.add(new BlockTimerExpiry(round)); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
66 changes: 66 additions & 0 deletions
66
...s/ibft/src/main/java/tech/pegasys/pantheon/consensus/ibft/ibftevent/BlockTimerExpiry.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
/* | ||
* Copyright 2018 ConsenSys AG. | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with | ||
* the License. You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on | ||
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the | ||
* specific language governing permissions and limitations under the License. | ||
*/ | ||
package tech.pegasys.pantheon.consensus.ibft.ibftevent; | ||
|
||
import tech.pegasys.pantheon.consensus.ibft.ConsensusRoundIdentifier; | ||
import tech.pegasys.pantheon.consensus.ibft.IbftEvent; | ||
import tech.pegasys.pantheon.consensus.ibft.IbftEvents.Type; | ||
|
||
import java.util.Objects; | ||
|
||
import com.google.common.base.MoreObjects; | ||
|
||
/** Event indicating a block timer has expired */ | ||
public final class BlockTimerExpiry implements IbftEvent { | ||
private final ConsensusRoundIdentifier roundIdentifier; | ||
|
||
/** | ||
* Constructor for a BlockTimerExpiry event | ||
* | ||
* @param roundIdentifier The roundIdentifier that the expired timer belonged to | ||
*/ | ||
public BlockTimerExpiry(final ConsensusRoundIdentifier roundIdentifier) { | ||
this.roundIdentifier = roundIdentifier; | ||
} | ||
|
||
@Override | ||
public Type getType() { | ||
return Type.BLOCK_TIMER_EXPIRY; | ||
} | ||
|
||
public ConsensusRoundIdentifier getRoundIndentifier() { | ||
return roundIdentifier; | ||
} | ||
|
||
@Override | ||
public String toString() { | ||
return MoreObjects.toStringHelper(this).add("Round Identifier", roundIdentifier).toString(); | ||
} | ||
|
||
@Override | ||
public boolean equals(final Object o) { | ||
if (this == o) { | ||
return true; | ||
} | ||
if (o == null || getClass() != o.getClass()) { | ||
return false; | ||
} | ||
final BlockTimerExpiry that = (BlockTimerExpiry) o; | ||
return Objects.equals(roundIdentifier, that.roundIdentifier); | ||
} | ||
|
||
@Override | ||
public int hashCode() { | ||
return Objects.hash(roundIdentifier); | ||
} | ||
} |
Oops, something went wrong.