Skip to content

Commit

Permalink
fix: fallen behind detection (#11480)
Browse files Browse the repository at this point in the history
Signed-off-by: Cody Littley <[email protected]>
  • Loading branch information
cody-littley authored Feb 20, 2024
1 parent e54e5c3 commit ec95616
Show file tree
Hide file tree
Showing 33 changed files with 1,161 additions and 1,111 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -287,6 +287,8 @@ public class SwirldsPlatform implements Platform {
/** thread-queue responsible for hashing states */
private final QueueThread<ReservedSignedState> stateHashSignQueue;

private final AncientMode ancientMode;

/**
* the browser gives the Platform what app to run. There can be multiple Platforms on one computer.
*
Expand Down Expand Up @@ -314,6 +316,11 @@ public class SwirldsPlatform implements Platform {

this.platformContext = Objects.requireNonNull(platformContext, "platformContext");

ancientMode = platformContext
.getConfiguration()
.getConfigData(EventConfig.class)
.getAncientMode();

this.emergencyRecoveryManager = Objects.requireNonNull(emergencyRecoveryManager, "emergencyRecoveryManager");
final Time time = Time.getCurrent();

Expand Down Expand Up @@ -403,20 +410,14 @@ public class SwirldsPlatform implements Platform {

// When we perform the migration to using birth round bounding, we will need to read
// the old type and start writing the new type.
final AncientMode currentFileType = platformContext
.getConfiguration()
.getConfigData(EventConfig.class)
.useBirthRoundAncientThreshold()
? AncientMode.BIRTH_ROUND_THRESHOLD
: AncientMode.GENERATION_THRESHOLD;

initialPcesFiles = PcesFileReader.readFilesFromDisk(
platformContext,
recycleBin,
databaseDirectory,
initialState.getRound(),
preconsensusEventStreamConfig.permitGaps(),
currentFileType);
ancientMode);

preconsensusEventFileManager =
new PcesFileManager(platformContext, initialPcesFiles, selfId, initialState.getRound());
Expand Down Expand Up @@ -683,7 +684,6 @@ public class SwirldsPlatform implements Platform {
epochHash,
shadowGraph,
emergencyRecoveryManager,
consensusRef,
platformWiring.getGossipEventInput()::put,
platformWiring.getIntakeQueueSizeSupplier(),
swirldStateManager,
Expand All @@ -699,10 +699,7 @@ public class SwirldsPlatform implements Platform {
platformContext.getConfiguration().getConfigData(ConsensusConfig.class),
consensusMetrics,
getAddressBook(),
platformContext
.getConfiguration()
.getConfigData(EventConfig.class)
.getAncientMode()));
ancientMode));

if (startedFromGenesis) {
initialMinimumGenerationNonAncient = 0;
Expand Down Expand Up @@ -845,7 +842,15 @@ private void loadStateIntoConsensus(@NonNull final SignedState signedState) {
Objects.requireNonNull(signedState);

consensusRef.get().loadFromSignedState(signedState);
shadowGraph.startWithExpiredThreshold(consensusRef.get().getMinGenerationNonAncient());

// FUTURE WORK: this needs to be updated for birth round compatibility.
final NonAncientEventWindow eventWindow = new NonAncientEventWindow(
signedState.getRound(),
signedState.getState().getPlatformState().getMinimumGenerationNonAncient(),
signedState.getState().getPlatformState().getMinimumGenerationNonAncient(),
ancientMode);

shadowGraph.startWithEventWindow(eventWindow);

gossip.loadFromSignedState(signedState);
}
Expand Down Expand Up @@ -912,7 +917,7 @@ private void loadReconnectState(final SignedState signedState) {
signedState.getRound(),
signedState.getMinRoundGeneration(),
signedState.getMinRoundGeneration(),
AncientMode.getAncientMode(platformContext)));
ancientMode));

platformWiring.updateRunningHash(new RunningEventHashUpdate(signedState.getHashEventsCons(), true));
platformWiring.getPcesWriterRegisterDiscontinuityInput().inject(signedState.getRound());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -116,12 +116,21 @@ public AncientMode getAncientMode() {
return ancientMode;
}

/**
* The round that has come to consensus most recently.
*
* @return the latest round that has come to consensus
*/
public long getLatestConsensusRound() {
return latestConsensusRound;
}

/**
* The round that will come to consensus next.
*
* @return the pending round coming to consensus, i.e. 1 + the latestConsensusRound
*/
public long pendingConsensusRound() {
public long getPendingConsensusRound() {
return latestConsensusRound + 1;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ public List<GossipEvent> addEvent(@NonNull final GossipEvent event) {
if (eventWindow.isAncient(event)) {
// we can safely ignore ancient events
return null;
} else if (event.getHashedData().getBirthRound() <= eventWindow.pendingConsensusRound()) {
} else if (event.getHashedData().getBirthRound() <= eventWindow.getPendingConsensusRound()) {
// this is not a future event, no need to buffer it
return List.of(event);
}
Expand All @@ -113,7 +113,7 @@ public List<GossipEvent> updateEventWindow(@NonNull final NonAncientEventWindow
this.eventWindow = Objects.requireNonNull(eventWindow);

final List<GossipEvent> events = new ArrayList<>();
futureEvents.shiftWindow(eventWindow.pendingConsensusRound(), (round, roundEvents) -> {
futureEvents.shiftWindow(eventWindow.getPendingConsensusRound(), (round, roundEvents) -> {
for (final GossipEvent event : roundEvents) {
if (!eventWindow.isAncient(event)) {
events.add(event);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -438,7 +438,7 @@ private GossipEvent assembleEventObject(@Nullable final EventDescriptor otherPar
lastSelfEvent,
otherParent == null ? Collections.emptyList() : Collections.singletonList(otherParent),
nonAncientEventWindow.getAncientMode() == AncientMode.BIRTH_ROUND_THRESHOLD
? nonAncientEventWindow.pendingConsensusRound()
? nonAncientEventWindow.getPendingConsensusRound()
: ConsensusConstants.ROUND_FIRST,
timeCreated,
transactionSupplier.getTransactions());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
import static com.swirlds.metrics.api.Metrics.PLATFORM_CATEGORY;
import static com.swirlds.platform.consensus.ConsensusConstants.ROUND_FIRST;
import static com.swirlds.platform.consensus.ConsensusConstants.ROUND_NEGATIVE_INFINITY;
import static com.swirlds.platform.consensus.GraphGenerations.FIRST_GENERATION;
import static com.swirlds.platform.system.events.EventConstants.FIRST_GENERATION;

import com.swirlds.base.time.Time;
import com.swirlds.common.context.PlatformContext;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@
import com.swirlds.common.notification.NotificationEngine;
import com.swirlds.common.platform.NodeId;
import com.swirlds.common.threading.manager.ThreadManager;
import com.swirlds.platform.Consensus;
import com.swirlds.platform.crypto.KeysAndCerts;
import com.swirlds.platform.event.GossipEvent;
import com.swirlds.platform.gossip.shadowgraph.Shadowgraph;
Expand All @@ -42,7 +41,6 @@
import edu.umd.cs.findbugs.annotations.NonNull;
import edu.umd.cs.findbugs.annotations.Nullable;
import java.util.Objects;
import java.util.concurrent.atomic.AtomicReference;
import java.util.function.Consumer;
import java.util.function.LongSupplier;
import java.util.function.Supplier;
Expand Down Expand Up @@ -72,7 +70,6 @@ private GossipFactory() {}
* @param epochHash the epoch hash of the initial state
* @param shadowGraph contains non-ancient events
* @param emergencyRecoveryManager handles emergency recovery
* @param consensusRef a pointer to consensus
* @param receivedEventHandler handles events received from other nodes
* @param intakeQueueSizeSupplier a supplier for the size of the event intake queue
* @param swirldStateManager manages the mutable state
Expand All @@ -97,7 +94,6 @@ public static Gossip buildGossip(
@Nullable final Hash epochHash,
@NonNull final Shadowgraph shadowGraph,
@NonNull final EmergencyRecoveryManager emergencyRecoveryManager,
@NonNull final AtomicReference<Consensus> consensusRef,
@NonNull final Consumer<GossipEvent> receivedEventHandler,
@NonNull final LongSupplier intakeQueueSizeSupplier,
@NonNull final SwirldStateManager swirldStateManager,
Expand All @@ -119,7 +115,6 @@ public static Gossip buildGossip(
Objects.requireNonNull(appVersion);
Objects.requireNonNull(shadowGraph);
Objects.requireNonNull(emergencyRecoveryManager);
Objects.requireNonNull(consensusRef);
Objects.requireNonNull(receivedEventHandler);
Objects.requireNonNull(intakeQueueSizeSupplier);
Objects.requireNonNull(swirldStateManager);
Expand Down Expand Up @@ -160,7 +155,6 @@ public static Gossip buildGossip(
epochHash,
shadowGraph,
emergencyRecoveryManager,
consensusRef,
receivedEventHandler,
intakeQueueSizeSupplier,
swirldStateManager,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
/*
* Copyright (C) 2024 Hedera Hashgraph, LLC
*
* 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 com.swirlds.platform.gossip.shadowgraph;

import com.swirlds.platform.consensus.NonAncientEventWindow;
import edu.umd.cs.findbugs.annotations.NonNull;
import java.util.Objects;

/**
* An event window that has been reserved in the shadowgraph. While this reservation is held, the shadowgraph will not
* unlink any events that are non-expired with respect to the reserved window.
*/
public class ReservedEventWindow implements AutoCloseable {
private final NonAncientEventWindow eventWindow;
private final ShadowgraphReservation shadowgraphReservation;

/**
* Constructor.
*
* @param eventWindow the event window
* @param shadowgraphReservation the shadowgraph reservation
*/
public ReservedEventWindow(
@NonNull final NonAncientEventWindow eventWindow,
@NonNull final ShadowgraphReservation shadowgraphReservation) {
this.eventWindow = Objects.requireNonNull(eventWindow);
this.shadowgraphReservation = Objects.requireNonNull(shadowgraphReservation);
}

/**
* {@inheritDoc}
*/
@Override
public void close() {
shadowgraphReservation.close();
}

/**
* Get the reserved event window. No events will be unlinked that are non-expired with respect to this window, as
* long as this reservation is held.
*
* @return the reserved event window
*/
@NonNull
public NonAncientEventWindow getEventWindow() {
return eventWindow;
}

/**
* Get the number of reservations in the underlying shadowgraph reservation. Exposed for unit tests.
*
* @return the number of reservations
*/
public long getReservationCount() {
return shadowgraphReservation.getReservationCount();
}
}
Loading

0 comments on commit ec95616

Please sign in to comment.