Skip to content

Commit cbc5f95

Browse files
committed
refactor: 21915 Introduce StateLifecycleManager
Signed-off-by: Ivan Malygin <[email protected]>
1 parent 008b99b commit cbc5f95

File tree

43 files changed

+581
-485
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

43 files changed

+581
-485
lines changed

hedera-node/hedera-app/src/main/java/com/hedera/node/app/HederaVirtualMapState.java

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -70,20 +70,6 @@ protected HederaVirtualMapState copyingConstructor() {
7070
return new HederaVirtualMapState(this);
7171
}
7272

73-
/**
74-
* Creates a new instance of {@link HederaVirtualMapState} with the specified {@link VirtualMap}.
75-
*
76-
* @param virtualMap the virtual map whose metrics must already be registered
77-
* @param metrics the platform metric instance to use when creating the new instance of state
78-
* @param time the time instance to use when creating the new instance of state
79-
* @return a new instance of {@link HederaVirtualMapState}
80-
*/
81-
@Override
82-
protected HederaVirtualMapState newInstance(
83-
@NonNull final VirtualMap virtualMap, @NonNull final Metrics metrics, @NonNull final Time time) {
84-
return new HederaVirtualMapState(virtualMap, metrics, time);
85-
}
86-
8773
/**
8874
* {@inheritDoc}
8975
*/

hedera-node/hedera-app/src/test/java/com/hedera/node/app/state/merkle/SerializationTest.java

Lines changed: 30 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -11,18 +11,22 @@
1111
import com.hedera.node.app.spi.fixtures.TestSchema;
1212
import com.hedera.node.app.spi.migrate.StartupNetworks;
1313
import com.hedera.node.config.data.HederaConfig;
14+
import com.swirlds.base.test.fixtures.time.FakeTime;
1415
import com.swirlds.common.io.utility.LegacyTemporaryFileBuilder;
1516
import com.swirlds.common.merkle.utility.MerkleTreeSnapshotReader;
17+
import com.swirlds.common.metrics.noop.NoOpMetrics;
1618
import com.swirlds.config.api.Configuration;
1719
import com.swirlds.config.extensions.sources.SimpleConfigSource;
1820
import com.swirlds.config.extensions.test.fixtures.TestConfigBuilder;
1921
import com.swirlds.platform.state.signed.SignedState;
2022
import com.swirlds.platform.test.fixtures.state.RandomSignedStateGenerator;
2123
import com.swirlds.state.MerkleNodeState;
2224
import com.swirlds.state.State;
25+
import com.swirlds.state.StateLifecycleManager;
2326
import com.swirlds.state.lifecycle.MigrationContext;
2427
import com.swirlds.state.lifecycle.Schema;
2528
import com.swirlds.state.lifecycle.StateDefinition;
29+
import com.swirlds.state.merkle.StateLifecycleManagerImpl;
2630
import com.swirlds.state.merkle.disk.OnDiskReadableKVState;
2731
import com.swirlds.state.merkle.disk.OnDiskWritableKVState;
2832
import com.swirlds.state.spi.ReadableKVState;
@@ -157,11 +161,12 @@ private void forceFlush(ReadableKVState<?, ?> state) {
157161
@ParameterizedTest
158162
@ValueSource(booleans = {true, false})
159163
void simpleReadAndWrite(boolean forceFlush) throws IOException, ConstructableRegistryException {
160-
final var schemaV1 = createV1Schema();
161-
final var originalTree = createMerkleHederaState(schemaV1);
164+
final Schema schemaV1 = createV1Schema();
165+
final StateLifecycleManager stateLifecycleManager = createStateLifecycleManager(schemaV1);
166+
final MerkleNodeState originalTree = stateLifecycleManager.getMutableState();
162167

163168
// When we serialize it to bytes and deserialize it back into a tree
164-
MerkleNodeState copy = originalTree.copy(); // make a copy to make VM flushable
169+
MerkleNodeState copy = stateLifecycleManager.copyMutableState(); // make a copy to make VM flushable
165170
final byte[] serializedBytes;
166171
if (forceFlush) {
167172
// Force flush the VMs to disk to test serialization and deserialization
@@ -188,21 +193,22 @@ void simpleReadAndWrite(boolean forceFlush) throws IOException, ConstructableReg
188193

189194
@Test
190195
void snapshot() throws IOException {
191-
final var schemaV1 = createV1Schema();
192-
final var originalTree = createMerkleHederaState(schemaV1);
193-
final var tempDir = LegacyTemporaryFileBuilder.buildTemporaryDirectory(config);
196+
final Schema<SemanticVersion> schemaV1 = createV1Schema();
197+
final StateLifecycleManager stateLifecycleManager = createStateLifecycleManager(schemaV1);
198+
final Path tempDir = LegacyTemporaryFileBuilder.buildTemporaryDirectory(config);
199+
final MerkleNodeState originalTree = stateLifecycleManager.getMutableState();
194200

195201
// prepare the tree and create a snapshot
196-
originalTree.copy().release();
202+
stateLifecycleManager.copyMutableState().release();
197203
originalTree.computeHash();
198-
originalTree.createSnapshot(tempDir);
204+
stateLifecycleManager.setSnapshotSource(() -> originalTree);
205+
stateLifecycleManager.createSnapshot(tempDir);
199206

200207
final MerkleNodeState state =
201-
originalTree.loadSnapshot(tempDir.resolve(MerkleTreeSnapshotReader.SIGNED_STATE_FILE_NAME));
208+
stateLifecycleManager.loadSnapshot(tempDir.resolve(MerkleTreeSnapshotReader.SIGNED_STATE_FILE_NAME));
202209
initServices(schemaV1, state);
203210
assertTree(state);
204211

205-
originalTree.release();
206212
state.release();
207213
}
208214

@@ -213,13 +219,16 @@ void snapshot() throws IOException {
213219
*/
214220
@Test
215221
void dualReadAndWrite() throws IOException, ConstructableRegistryException {
216-
final var schemaV1 = createV1Schema();
217-
final var originalTree = createMerkleHederaState(schemaV1);
222+
final Schema<SemanticVersion> schemaV1 = createV1Schema();
223+
final StateLifecycleManager stateLifecycleManager = createStateLifecycleManager(schemaV1);
224+
final MerkleNodeState originalTree = stateLifecycleManager.getMutableState();
218225

219-
MerkleNodeState copy = originalTree.copy(); // make a copy to make VM flushable
226+
MerkleNodeState copy = stateLifecycleManager.copyMutableState(); // make a copy to make VM flushable
220227

221228
forceFlush(originalTree.getReadableStates(FIRST_SERVICE).get(FRUIT_STATE_ID));
222-
copy.copy().release(); // make a fast copy because we can only write to disk an immutable copy
229+
stateLifecycleManager
230+
.copyMutableState()
231+
.release(); // make a fast copy because we can only write to disk an immutable copy
223232
copy.getRoot().getHash();
224233
final byte[] serializedBytes = writeTree(copy.getRoot(), dir);
225234

@@ -275,7 +284,7 @@ private void initServices(Schema<SemanticVersion> schemaV1, MerkleNodeState load
275284
loadedTree.getRoot().migrate(MINIMUM_SUPPORTED_VERSION);
276285
}
277286

278-
private MerkleNodeState createMerkleHederaState(Schema schemaV1) {
287+
private StateLifecycleManager createStateLifecycleManager(Schema schemaV1) {
279288
final SignedState randomState =
280289
new RandomSignedStateGenerator().setRound(1).build();
281290

@@ -295,7 +304,12 @@ private MerkleNodeState createMerkleHederaState(Schema schemaV1) {
295304
migrationStateChanges,
296305
startupNetworks,
297306
TEST_PLATFORM_STATE_FACADE);
298-
return originalTreeCopy;
307+
308+
final StateLifecycleManager<SignedState> stateLifecycleManager =
309+
new StateLifecycleManagerImpl<>(new NoOpMetrics(), new FakeTime(), TestVirtualMapState::new);
310+
311+
stateLifecycleManager.initState(originalTreeCopy, true);
312+
return stateLifecycleManager;
299313
}
300314

301315
private static void populateVmCache(State loadedTree) {

hedera-node/hedera-app/src/testFixtures/java/com/hedera/node/app/fixtures/state/FakeState.java

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,6 @@
3333
import com.swirlds.state.test.fixtures.MapWritableStates;
3434
import com.swirlds.state.test.fixtures.merkle.TestVirtualMapState;
3535
import edu.umd.cs.findbugs.annotations.NonNull;
36-
import java.nio.file.Path;
3736
import java.util.ArrayList;
3837
import java.util.List;
3938
import java.util.Map;
@@ -303,9 +302,4 @@ public long queueElementPath(final int stateId, @NonNull final Bytes expectedVal
303302
public void initializeState(@NonNull final StateMetadata<?, ?> md) {
304303
// do nothing
305304
}
306-
307-
@Override
308-
public MerkleNodeState loadSnapshot(@NonNull final Path targetPath) {
309-
throw new UnsupportedOperationException();
310-
}
311305
}

hedera-state-validator/src/main/java/com/hedera/statevalidation/blockstream/BlockStreamRecoveryWorkflow.java

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
import com.hedera.hapi.block.stream.Block;
99
import com.hedera.hapi.block.stream.BlockItem;
1010
import com.hedera.hapi.block.stream.output.StateChanges;
11+
import com.hedera.node.app.HederaVirtualMapState;
1112
import com.hedera.node.app.hapi.utils.blocks.BlockStreamAccess;
1213
import com.hedera.node.app.hapi.utils.blocks.BlockStreamUtils;
1314
import com.hedera.statevalidation.util.PlatformContextHelper;
@@ -18,6 +19,8 @@
1819
import com.swirlds.platform.state.snapshot.DeserializedSignedState;
1920
import com.swirlds.platform.state.snapshot.SignedStateFileWriter;
2021
import com.swirlds.state.MerkleNodeState;
22+
import com.swirlds.state.StateLifecycleManager;
23+
import com.swirlds.state.merkle.StateLifecycleManagerImpl;
2124
import com.swirlds.state.spi.CommittableWritableStates;
2225
import edu.umd.cs.findbugs.annotations.NonNull;
2326
import java.io.IOException;
@@ -149,9 +152,14 @@ public void applyBlocks(
149152
false,
150153
DEFAULT_PLATFORM_STATE_FACADE);
151154

155+
final StateLifecycleManager<SignedState> stateLifecycleManager = new StateLifecycleManagerImpl<>(
156+
platformContext.getMetrics(),
157+
platformContext.getTime(),
158+
vm -> new HederaVirtualMapState(vm, platformContext.getMetrics(), platformContext.getTime()));
159+
stateLifecycleManager.setSnapshotSource(signedState);
152160
try {
153161
SignedStateFileWriter.writeSignedStateFilesToDirectory(
154-
platformContext, selfId, outputPath, signedState, DEFAULT_PLATFORM_STATE_FACADE);
162+
platformContext, selfId, outputPath, DEFAULT_PLATFORM_STATE_FACADE, stateLifecycleManager);
155163
} catch (IOException e) {
156164
throw new RuntimeException(e);
157165
}

platform-sdk/consensus-otter-tests/src/testFixtures/java/org/hiero/otter/fixtures/app/OtterAppState.java

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -82,12 +82,6 @@ protected OtterAppState copyingConstructor() {
8282
return new OtterAppState(this);
8383
}
8484

85-
@Override
86-
protected OtterAppState newInstance(
87-
@NonNull final VirtualMap virtualMap, @NonNull final Metrics metrics, @NonNull final Time time) {
88-
return new OtterAppState(virtualMap, metrics, time);
89-
}
90-
9185
/**
9286
* {@inheritDoc}
9387
*/

platform-sdk/platform-apps/tests/ConsistencyTestingTool/src/main/java/com/swirlds/demo/consistency/ConsistencyTestingToolState.java

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -119,12 +119,6 @@ protected ConsistencyTestingToolState copyingConstructor() {
119119
return new ConsistencyTestingToolState(this);
120120
}
121121

122-
@Override
123-
protected ConsistencyTestingToolState newInstance(
124-
@NonNull final VirtualMap virtualMap, @NonNull final Metrics metrics, @NonNull final Time time) {
125-
return new ConsistencyTestingToolState(virtualMap, metrics, time);
126-
}
127-
128122
/**
129123
* Initialize the state
130124
*/

platform-sdk/platform-apps/tests/ISSTestingTool/src/main/java/com/swirlds/demo/iss/ISSTestingToolState.java

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -98,12 +98,6 @@ protected ISSTestingToolState copyingConstructor() {
9898
return new ISSTestingToolState(this);
9999
}
100100

101-
@Override
102-
protected ISSTestingToolState newInstance(
103-
@NonNull final VirtualMap virtualMap, @NonNull final Metrics metrics, @NonNull final Time time) {
104-
return new ISSTestingToolState(virtualMap, metrics, time);
105-
}
106-
107101
public void initState(InitTrigger trigger, Platform platform) {
108102
throwIfImmutable();
109103

platform-sdk/platform-apps/tests/MigrationTestingTool/src/main/java/com/swirlds/demo/migration/MigrationTestingToolState.java

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -32,12 +32,6 @@ protected MigrationTestingToolState copyingConstructor() {
3232
return new MigrationTestingToolState(this);
3333
}
3434

35-
@Override
36-
protected MigrationTestingToolState newInstance(
37-
@NonNull final VirtualMap virtualMap, @NonNull final Metrics metrics, @NonNull final Time time) {
38-
return new MigrationTestingToolState(virtualMap, metrics, time);
39-
}
40-
4135
/**
4236
* {@inheritDoc}
4337
*/

platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/SwirldsPlatform.java

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,6 @@
3838
import com.swirlds.platform.publisher.PlatformPublisher;
3939
import com.swirlds.platform.reconnect.DefaultSignedStateValidator;
4040
import com.swirlds.platform.reconnect.ReconnectController;
41-
import com.swirlds.platform.state.SwirldStateManager;
4241
import com.swirlds.platform.state.nexus.DefaultLatestCompleteStateNexus;
4342
import com.swirlds.platform.state.nexus.LatestCompleteStateNexus;
4443
import com.swirlds.platform.state.nexus.LockFreeStateNexus;
@@ -59,6 +58,7 @@
5958
import com.swirlds.platform.wiring.PlatformComponents;
6059
import com.swirlds.platform.wiring.PlatformCoordinator;
6160
import com.swirlds.state.State;
61+
import com.swirlds.state.StateLifecycleManager;
6262
import edu.umd.cs.findbugs.annotations.NonNull;
6363
import java.time.Duration;
6464
import java.util.List;
@@ -138,6 +138,11 @@ public class SwirldsPlatform implements Platform {
138138
*/
139139
private final SavedStateController savedStateController;
140140

141+
/**
142+
* Manages the lifecycle of the state.
143+
*/
144+
private final StateLifecycleManager<SignedState> stateLifecycleManager;
145+
141146
/**
142147
* Encapsulated wiring for the platform.
143148
*/
@@ -185,7 +190,8 @@ public SwirldsPlatform(@NonNull final PlatformComponentBuilder builder) {
185190

186191
final LatestCompleteStateNexus latestCompleteStateNexus = new DefaultLatestCompleteStateNexus(platformContext);
187192

188-
savedStateController = new DefaultSavedStateController(platformContext);
193+
savedStateController = new DefaultSavedStateController(platformContext, blocks.stateLifecycleManager());
194+
stateLifecycleManager = blocks.stateLifecycleManager();
189195

190196
final SignedStateMetrics signedStateMetrics = new SignedStateMetrics(platformContext.getMetrics());
191197
final StateSignatureCollector stateSignatureCollector =
@@ -211,15 +217,15 @@ public SwirldsPlatform(@NonNull final PlatformComponentBuilder builder) {
211217
initializeState(this, platformContext, initialState, blocks.consensusStateEventHandler(), platformStateFacade);
212218

213219
// This object makes a copy of the state. After this point, initialState becomes immutable.
214-
final SwirldStateManager swirldStateManager = blocks.swirldStateManager();
215-
swirldStateManager.setState(initialState.getState(), true);
216-
platformStateFacade.setCreationSoftwareVersionTo(swirldStateManager.getConsensusState(), blocks.appVersion());
220+
final StateLifecycleManager stateLifecycleManager = blocks.stateLifecycleManager();
221+
stateLifecycleManager.initState(initialState.getState(), true);
222+
platformStateFacade.setCreationSoftwareVersionTo(stateLifecycleManager.getMutableState(), blocks.appVersion());
217223

218224
final EventWindowManager eventWindowManager = new DefaultEventWindowManager();
219225

220226
blocks.freezeCheckHolder()
221227
.setFreezeCheckRef(instant ->
222-
platformStateFacade.isInFreezePeriod(instant, swirldStateManager.getConsensusState()));
228+
platformStateFacade.isInFreezePeriod(instant, stateLifecycleManager.getMutableState()));
223229

224230
final AppNotifier appNotifier = new DefaultAppNotifier(blocks.notificationEngine());
225231

@@ -231,7 +237,7 @@ public SwirldsPlatform(@NonNull final PlatformComponentBuilder builder) {
231237
this,
232238
platformContext,
233239
platformCoordinator,
234-
swirldStateManager,
240+
stateLifecycleManager,
235241
savedStateController,
236242
blocks.consensusStateEventHandler(),
237243
blocks.reservedSignedStateResultPromise(),
@@ -382,6 +388,7 @@ public void performPcesRecovery() {
382388
} else {
383389
final SignedState signedState = reservedState.get();
384390
signedState.markAsStateToSave(StateToDiskReason.PCES_RECOVERY_COMPLETE);
391+
stateLifecycleManager.setSnapshotSource(signedState);
385392

386393
final StateDumpRequest request =
387394
StateDumpRequest.create(signedState.reserve("dumping PCES recovery state"));

platform-sdk/swirlds-platform-core/src/main/java/com/swirlds/platform/builder/PlatformBuilder.java

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -34,14 +34,15 @@
3434
import com.swirlds.platform.reconnect.FallenBehindMonitor;
3535
import com.swirlds.platform.scratchpad.Scratchpad;
3636
import com.swirlds.platform.state.ConsensusStateEventHandler;
37-
import com.swirlds.platform.state.SwirldStateManager;
3837
import com.swirlds.platform.state.iss.IssScratchpad;
3938
import com.swirlds.platform.state.service.PlatformStateFacade;
4039
import com.swirlds.platform.state.signed.ReservedSignedState;
4140
import com.swirlds.platform.system.Platform;
4241
import com.swirlds.platform.wiring.PlatformComponents;
4342
import com.swirlds.platform.wiring.PlatformWiring;
4443
import com.swirlds.state.MerkleNodeState;
44+
import com.swirlds.state.StateLifecycleManager;
45+
import com.swirlds.state.merkle.StateLifecycleManagerImpl;
4546
import com.swirlds.virtualmap.VirtualMap;
4647
import edu.umd.cs.findbugs.annotations.NonNull;
4748
import java.io.IOException;
@@ -433,7 +434,8 @@ public PlatformComponentBuilder buildComponentBuilder() {
433434
final ApplicationCallbacks callbacks =
434435
new ApplicationCallbacks(preconsensusEventConsumer, snapshotOverrideConsumer, staleEventConsumer);
435436

436-
final SwirldStateManager swirldStateManager = new SwirldStateManager(platformContext, currentRoster);
437+
final StateLifecycleManager stateLifecycleManager = new StateLifecycleManagerImpl(
438+
platformContext.getMetrics(), platformContext.getTime(), createStateFromVirtualMap);
437439

438440
if (model == null) {
439441
final WiringConfig wiringConfig = platformContext.getConfiguration().getConfigData(WiringConfig.class);
@@ -495,7 +497,7 @@ public PlatformComponentBuilder buildComponentBuilder() {
495497
issScratchpad,
496498
NotificationEngine.buildEngine(getStaticThreadManager()),
497499
new AtomicReference<>(),
498-
swirldStateManager,
500+
stateLifecycleManager,
499501
new AtomicReference<>(),
500502
firstPlatform,
501503
consensusStateEventHandler,

0 commit comments

Comments
 (0)