Skip to content

Commit

Permalink
Moved service class registration to StateUtils of `swirlds-state-im…
Browse files Browse the repository at this point in the history
…pl`. Added missing registration to PTT.

Signed-off-by: Ivan Malygin <[email protected]>
  • Loading branch information
imalygin committed Nov 15, 2024
1 parent c31e88e commit 6ed59af
Show file tree
Hide file tree
Showing 4 changed files with 109 additions and 155 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
import static com.hedera.node.app.state.merkle.VersionUtils.alreadyIncludesStateDefs;
import static com.hedera.node.app.state.merkle.VersionUtils.isSoOrdered;
import static com.hedera.node.app.workflows.handle.metric.UnavailableMetrics.UNAVAILABLE_METRICS;
import static com.swirlds.state.merkle.StateUtils.registerWithSystem;
import static java.util.Objects.requireNonNull;

import com.hedera.hapi.node.base.SemanticVersion;
Expand All @@ -31,9 +32,7 @@
import com.hedera.node.app.services.MigrationStateChanges;
import com.hedera.node.app.spi.state.FilteredReadableStates;
import com.hedera.node.app.spi.state.FilteredWritableStates;
import com.swirlds.common.constructable.ClassConstructorPair;
import com.swirlds.common.constructable.ConstructableRegistry;
import com.swirlds.common.constructable.ConstructableRegistryException;
import com.swirlds.common.crypto.DigestType;
import com.swirlds.config.api.Configuration;
import com.swirlds.merkle.map.MerkleMap;
Expand All @@ -51,16 +50,10 @@
import com.swirlds.state.lifecycle.info.NetworkInfo;
import com.swirlds.state.merkle.StateMetadata;
import com.swirlds.state.merkle.StateUtils;
import com.swirlds.state.merkle.disk.OnDiskKey;
import com.swirlds.state.merkle.disk.OnDiskKeySerializer;
import com.swirlds.state.merkle.disk.OnDiskValue;
import com.swirlds.state.merkle.disk.OnDiskValueSerializer;
import com.swirlds.state.merkle.memory.InMemoryValue;
import com.swirlds.state.merkle.memory.InMemoryWritableKVState;
import com.swirlds.state.merkle.queue.QueueNode;
import com.swirlds.state.merkle.singleton.SingletonNode;
import com.swirlds.state.merkle.singleton.StringLeaf;
import com.swirlds.state.merkle.singleton.ValueLeaf;
import com.swirlds.state.spi.WritableStates;
import com.swirlds.virtualmap.VirtualMap;
import edu.umd.cs.findbugs.annotations.NonNull;
Expand Down Expand Up @@ -151,7 +144,7 @@ public SchemaRegistry register(@NonNull Schema schema) {
schema.statesToCreate(bootstrapConfig).forEach(def -> {
//noinspection rawtypes,unchecked
final var md = new StateMetadata<>(serviceName, schema, def);
registerWithSystem(md);
registerWithSystem(md, constructableRegistry);
});

return this;
Expand Down Expand Up @@ -380,81 +373,4 @@ private RedefinedWritableStates applyStateDefinitions(
final var newStates = new FilteredWritableStates(writableStates, remainingStates);
return new RedefinedWritableStates(writableStates, newStates);
}

/**
* Registers with the {@link ConstructableRegistry} system a class ID and a class. While this
* will only be used for in-memory states, it is safe to register for on-disk ones as well.
*
* <p>The implementation will take the service name and the state key and compute a hash for it.
* It will then convert the hash to a long, and use that as the class ID. It will then register
* an {@link InMemoryWritableKVState}'s value merkle type to be deserialized, answering with the
* generated class ID.
*
* @param md The state metadata
*/
@SuppressWarnings({"rawtypes", "unchecked"})
private void registerWithSystem(@NonNull final StateMetadata md) {
// Register with the system the uniqueId as the "classId" of an InMemoryValue. There can be
// multiple id's associated with InMemoryValue. The secret is that the supplier captures the
// various delegate writers and parsers, and so can parse/write different types of data
// based on the id.
try {
constructableRegistry.registerConstructable(new ClassConstructorPair(
InMemoryValue.class,
() -> new InMemoryValue(
md.inMemoryValueClassId(),
md.stateDefinition().keyCodec(),
md.stateDefinition().valueCodec())));
constructableRegistry.registerConstructable(new ClassConstructorPair(
OnDiskKey.class,
() -> new OnDiskKey<>(
md.onDiskKeyClassId(), md.stateDefinition().keyCodec())));
constructableRegistry.registerConstructable(new ClassConstructorPair(
OnDiskKeySerializer.class,
() -> new OnDiskKeySerializer<>(
md.onDiskKeySerializerClassId(),
md.onDiskKeyClassId(),
md.stateDefinition().keyCodec())));
constructableRegistry.registerConstructable(new ClassConstructorPair(
OnDiskValue.class,
() -> new OnDiskValue<>(
md.onDiskValueClassId(), md.stateDefinition().valueCodec())));
constructableRegistry.registerConstructable(new ClassConstructorPair(
OnDiskValueSerializer.class,
() -> new OnDiskValueSerializer<>(
md.onDiskValueSerializerClassId(),
md.onDiskValueClassId(),
md.stateDefinition().valueCodec())));
constructableRegistry.registerConstructable(new ClassConstructorPair(
SingletonNode.class,
() -> new SingletonNode<>(
md.serviceName(),
md.stateDefinition().stateKey(),
md.singletonClassId(),
md.stateDefinition().valueCodec(),
null)));
constructableRegistry.registerConstructable(new ClassConstructorPair(
QueueNode.class,
() -> new QueueNode<>(
md.serviceName(),
md.stateDefinition().stateKey(),
md.queueNodeClassId(),
md.singletonClassId(),
md.stateDefinition().valueCodec())));
constructableRegistry.registerConstructable(new ClassConstructorPair(StringLeaf.class, StringLeaf::new));
constructableRegistry.registerConstructable(new ClassConstructorPair(
ValueLeaf.class,
() -> new ValueLeaf<>(
md.singletonClassId(), md.stateDefinition().valueCodec())));
} catch (ConstructableRegistryException e) {
// This is a fatal error.
throw new IllegalStateException(
"Failed to register with the system '"
+ serviceName
+ ":"
+ md.stateDefinition().stateKey()
+ "'",
e);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@

import static com.swirlds.logging.legacy.LogMarker.STARTUP;
import static com.swirlds.platform.util.NoOpMerkleStateLifecycles.NO_OP_MERKLE_STATE_LIFECYCLES;
import static com.swirlds.state.merkle.StateUtils.registerWithSystem;

import com.swirlds.common.constructable.ClassConstructorPair;
import com.swirlds.common.constructable.ConstructableRegistry;
Expand All @@ -32,15 +33,6 @@
import com.swirlds.platform.system.SwirldMain;
import com.swirlds.state.lifecycle.StateDefinition;
import com.swirlds.state.merkle.StateMetadata;
import com.swirlds.state.merkle.disk.OnDiskKey;
import com.swirlds.state.merkle.disk.OnDiskKeySerializer;
import com.swirlds.state.merkle.disk.OnDiskValue;
import com.swirlds.state.merkle.disk.OnDiskValueSerializer;
import com.swirlds.state.merkle.memory.InMemoryValue;
import com.swirlds.state.merkle.queue.QueueNode;
import com.swirlds.state.merkle.singleton.SingletonNode;
import com.swirlds.state.merkle.singleton.StringLeaf;
import com.swirlds.state.merkle.singleton.ValueLeaf;
import edu.umd.cs.findbugs.annotations.NonNull;
import edu.umd.cs.findbugs.annotations.Nullable;
import java.security.SecureRandom;
Expand Down Expand Up @@ -83,66 +75,7 @@ private static void registerPlatformClasses(ConstructableRegistry constructableR
final var schema = new V0540PlatformStateSchema();
final StateDefinition def = schema.statesToCreate().iterator().next();
final var md = new StateMetadata<>(PlatformStateService.NAME, schema, def);
try {
constructableRegistry.registerConstructable(new ClassConstructorPair(
InMemoryValue.class,
() -> new InMemoryValue(
md.inMemoryValueClassId(),
md.stateDefinition().keyCodec(),
md.stateDefinition().valueCodec())));
constructableRegistry.registerConstructable(new ClassConstructorPair(
OnDiskKey.class,
() -> new OnDiskKey<>(
md.onDiskKeyClassId(), md.stateDefinition().keyCodec())));
constructableRegistry.registerConstructable(new ClassConstructorPair(
OnDiskKeySerializer.class,
() -> new OnDiskKeySerializer<>(
md.onDiskKeySerializerClassId(),
md.onDiskKeyClassId(),
md.stateDefinition().keyCodec())));
constructableRegistry.registerConstructable(new ClassConstructorPair(
OnDiskValue.class,
() -> new OnDiskValue<>(
md.onDiskValueClassId(), md.stateDefinition().valueCodec())));
constructableRegistry.registerConstructable(new ClassConstructorPair(
OnDiskValueSerializer.class,
() -> new OnDiskValueSerializer<>(
md.onDiskValueSerializerClassId(),
md.onDiskValueClassId(),
md.stateDefinition().valueCodec())));
constructableRegistry.registerConstructable(new ClassConstructorPair(
SingletonNode.class,
() -> new SingletonNode<>(
md.serviceName(),
md.stateDefinition().stateKey(),
md.singletonClassId(),
md.stateDefinition().valueCodec(),
null)));
constructableRegistry.registerConstructable(new ClassConstructorPair(
QueueNode.class,
() -> new QueueNode<>(
md.serviceName(),
md.stateDefinition().stateKey(),
md.queueNodeClassId(),
md.singletonClassId(),
md.stateDefinition().valueCodec())));
constructableRegistry.registerConstructable(new ClassConstructorPair(StringLeaf.class, StringLeaf::new));
constructableRegistry.registerConstructable(new ClassConstructorPair(
ValueLeaf.class,
() -> new ValueLeaf<>(
md.singletonClassId(), md.stateDefinition().valueCodec())));
logger.info(
STARTUP.getMarker(),
"PlatformState classes are successfully registered with ConstructableRegistry");
} catch (ConstructableRegistryException e) {
// This is a fatal error.
throw new IllegalStateException(
"Failed to register with the system 'PlatformService'"
+ ":"
+ md.stateDefinition().stateKey()
+ "'",
e);
}
registerWithSystem(md, constructableRegistry);
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
import static com.swirlds.merkle.test.fixtures.map.lifecycle.SaveExpectedMapHandler.serialize;
import static com.swirlds.metrics.api.FloatFormats.FORMAT_6_2;
import static com.swirlds.metrics.api.FloatFormats.FORMAT_9_6;
import static com.swirlds.state.merkle.StateUtils.registerWithSystem;
import static java.lang.System.exit;

import com.fasterxml.jackson.core.JsonParser;
Expand Down Expand Up @@ -85,6 +86,8 @@
import com.swirlds.platform.listeners.ReconnectCompleteListener;
import com.swirlds.platform.listeners.StateWriteToDiskCompleteListener;
import com.swirlds.platform.state.MerkleStateRoot;
import com.swirlds.platform.state.service.PlatformStateService;
import com.swirlds.platform.state.service.schemas.V0540PlatformStateSchema;
import com.swirlds.platform.system.BasicSoftwareVersion;
import com.swirlds.platform.system.Platform;
import com.swirlds.platform.system.SwirldMain;
Expand All @@ -93,6 +96,8 @@
import com.swirlds.platform.system.state.notifications.NewSignedStateListener;
import com.swirlds.platform.system.status.PlatformStatus;
import com.swirlds.platform.util.NoOpMerkleStateLifecycles;
import com.swirlds.state.lifecycle.StateDefinition;
import com.swirlds.state.merkle.StateMetadata;
import com.swirlds.virtualmap.internal.merkle.VirtualLeafNode;
import edu.umd.cs.findbugs.annotations.NonNull;
import java.io.File;
Expand Down Expand Up @@ -159,12 +164,21 @@ public class PlatformTestingToolMain implements SwirldMain {
.getConstructor(PlatformTestingToolState.CLASS_ID)
.get()
.getClassId());
registerPlatformClasses(ConstructableRegistry.getInstance());
} catch (ConstructableRegistryException e) {
logger.error(STARTUP.getMarker(), "Failed to register PlatformTestingToolState", e);
throw new RuntimeException(e);
}
}

private static void registerPlatformClasses(ConstructableRegistry constructableRegistry) {
logger.info(STARTUP.getMarker(), "Registering PlatformState classes with ConstructableRegistry");
final var schema = new V0540PlatformStateSchema();
final StateDefinition def = schema.statesToCreate().iterator().next();
final var md = new StateMetadata<>(PlatformStateService.NAME, schema, def);
registerWithSystem(md, constructableRegistry);
}

/**
* save internal file logs and expected map to file while freezing;
* for restart test we should set `saveExpectedMapAtFreeze` to be true, so that
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,21 @@
import com.hedera.pbj.runtime.ParseException;
import com.hedera.pbj.runtime.io.stream.ReadableStreamingData;
import com.hedera.pbj.runtime.io.stream.WritableStreamingData;
import com.swirlds.common.constructable.ClassConstructorPair;
import com.swirlds.common.constructable.ConstructableRegistry;
import com.swirlds.common.constructable.ConstructableRegistryException;
import com.swirlds.common.utility.NonCryptographicHashing;
import com.swirlds.logging.legacy.LogMarker;
import com.swirlds.state.merkle.disk.OnDiskKey;
import com.swirlds.state.merkle.disk.OnDiskKeySerializer;
import com.swirlds.state.merkle.disk.OnDiskValue;
import com.swirlds.state.merkle.disk.OnDiskValueSerializer;
import com.swirlds.state.merkle.memory.InMemoryValue;
import com.swirlds.state.merkle.memory.InMemoryWritableKVState;
import com.swirlds.state.merkle.queue.QueueNode;
import com.swirlds.state.merkle.singleton.SingletonNode;
import com.swirlds.state.merkle.singleton.StringLeaf;
import com.swirlds.state.merkle.singleton.ValueLeaf;
import edu.umd.cs.findbugs.annotations.NonNull;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
Expand Down Expand Up @@ -249,4 +262,82 @@ private static boolean isAsciiLetter(char ch) {
private static boolean isAsciiNumber(char ch) {
return ch >= '0' && ch <= '9';
}

/**
* Registers with the {@link ConstructableRegistry} system a class ID and a class. While this
* will only be used for in-memory states, it is safe to register for on-disk ones as well.
*
* <p>The implementation will take the service name and the state key and compute a hash for it.
* It will then convert the hash to a long, and use that as the class ID. It will then register
* an {@link InMemoryWritableKVState}'s value merkle type to be deserialized, answering with the
* generated class ID.
*
* @param md The state metadata
*/
@SuppressWarnings({"rawtypes", "unchecked"})
public static void registerWithSystem(
@NonNull final StateMetadata md, @NonNull ConstructableRegistry constructableRegistry) {
// Register with the system the uniqueId as the "classId" of an InMemoryValue. There can be
// multiple id's associated with InMemoryValue. The secret is that the supplier captures the
// various delegate writers and parsers, and so can parse/write different types of data
// based on the id.
try {
constructableRegistry.registerConstructable(new ClassConstructorPair(
InMemoryValue.class,
() -> new InMemoryValue(
md.inMemoryValueClassId(),
md.stateDefinition().keyCodec(),
md.stateDefinition().valueCodec())));
constructableRegistry.registerConstructable(new ClassConstructorPair(
OnDiskKey.class,
() -> new OnDiskKey<>(
md.onDiskKeyClassId(), md.stateDefinition().keyCodec())));
constructableRegistry.registerConstructable(new ClassConstructorPair(
OnDiskKeySerializer.class,
() -> new OnDiskKeySerializer<>(
md.onDiskKeySerializerClassId(),
md.onDiskKeyClassId(),
md.stateDefinition().keyCodec())));
constructableRegistry.registerConstructable(new ClassConstructorPair(
OnDiskValue.class,
() -> new OnDiskValue<>(
md.onDiskValueClassId(), md.stateDefinition().valueCodec())));
constructableRegistry.registerConstructable(new ClassConstructorPair(
OnDiskValueSerializer.class,
() -> new OnDiskValueSerializer<>(
md.onDiskValueSerializerClassId(),
md.onDiskValueClassId(),
md.stateDefinition().valueCodec())));
constructableRegistry.registerConstructable(new ClassConstructorPair(
SingletonNode.class,
() -> new SingletonNode<>(
md.serviceName(),
md.stateDefinition().stateKey(),
md.singletonClassId(),
md.stateDefinition().valueCodec(),
null)));
constructableRegistry.registerConstructable(new ClassConstructorPair(
QueueNode.class,
() -> new QueueNode<>(
md.serviceName(),
md.stateDefinition().stateKey(),
md.queueNodeClassId(),
md.singletonClassId(),
md.stateDefinition().valueCodec())));
constructableRegistry.registerConstructable(new ClassConstructorPair(StringLeaf.class, StringLeaf::new));
constructableRegistry.registerConstructable(new ClassConstructorPair(
ValueLeaf.class,
() -> new ValueLeaf<>(
md.singletonClassId(), md.stateDefinition().valueCodec())));
} catch (ConstructableRegistryException e) {
// This is a fatal error.
throw new IllegalStateException(
"Failed to register with the system '"
+ md.serviceName()
+ ":"
+ md.stateDefinition().stateKey()
+ "'",
e);
}
}
}

0 comments on commit 6ed59af

Please sign in to comment.