From 71cd12f61841c98f12bd01917c7ca2b305e94206 Mon Sep 17 00:00:00 2001 From: Andrew Kerr Date: Mon, 12 Mar 2018 17:07:51 +0000 Subject: [PATCH] Throw if Raft version configured but not known. Log ignored versions. --- .../core/EnterpriseCoreEditionModule.java | 2 +- .../core/SupportedProtocolCreator.java | 63 ++++++++++++---- .../causalclustering/protocol/Protocol.java | 21 +++++- .../core/SupportedProtocolCreatorTest.java | 74 +++++++++++++++---- 4 files changed, 127 insertions(+), 33 deletions(-) diff --git a/enterprise/causal-clustering/src/main/java/org/neo4j/causalclustering/core/EnterpriseCoreEditionModule.java b/enterprise/causal-clustering/src/main/java/org/neo4j/causalclustering/core/EnterpriseCoreEditionModule.java index f66ac3f7c1b2f..d864f4d9fc506 100644 --- a/enterprise/causal-clustering/src/main/java/org/neo4j/causalclustering/core/EnterpriseCoreEditionModule.java +++ b/enterprise/causal-clustering/src/main/java/org/neo4j/causalclustering/core/EnterpriseCoreEditionModule.java @@ -239,7 +239,7 @@ public EnterpriseCoreEditionModule( final PlatformModule platformModule, long logThresholdMillis = config.get( CausalClusteringSettings.unknown_address_logging_throttle ).toMillis(); - SupportedProtocolCreator supportedProtocolCreator = new SupportedProtocolCreator( config ); + SupportedProtocolCreator supportedProtocolCreator = new SupportedProtocolCreator( config, logProvider ); ApplicationSupportedProtocols supportedApplicationProtocol = supportedProtocolCreator.createSupportedRaftProtocol(); Collection supportedModifierProtocols = supportedProtocolCreator.createSupportedModifierProtocols(); diff --git a/enterprise/causal-clustering/src/main/java/org/neo4j/causalclustering/core/SupportedProtocolCreator.java b/enterprise/causal-clustering/src/main/java/org/neo4j/causalclustering/core/SupportedProtocolCreator.java index 12f2e5e7892f6..b50e6a60c42b5 100644 --- a/enterprise/causal-clustering/src/main/java/org/neo4j/causalclustering/core/SupportedProtocolCreator.java +++ b/enterprise/causal-clustering/src/main/java/org/neo4j/causalclustering/core/SupportedProtocolCreator.java @@ -19,31 +19,56 @@ */ package org.neo4j.causalclustering.core; +import java.util.Collections; import java.util.List; -import java.util.Objects; +import java.util.Optional; +import java.util.function.Function; import java.util.stream.Collectors; import java.util.stream.Stream; import org.neo4j.causalclustering.protocol.Protocol; import org.neo4j.causalclustering.protocol.handshake.ApplicationSupportedProtocols; import org.neo4j.causalclustering.protocol.handshake.ModifierSupportedProtocols; -import org.neo4j.graphdb.config.Setting; +import org.neo4j.helpers.collection.Pair; import org.neo4j.kernel.configuration.Config; +import org.neo4j.logging.Log; +import org.neo4j.logging.LogProvider; import org.neo4j.stream.Streams; +import static org.neo4j.causalclustering.protocol.Protocol.ApplicationProtocolCategory.RAFT; +import static org.neo4j.causalclustering.protocol.Protocol.ModifierProtocolCategory.COMPRESSION; + public class SupportedProtocolCreator { private final Config config; + private final Log log; - public SupportedProtocolCreator( Config config ) + public SupportedProtocolCreator( Config config, LogProvider logProvider ) { this.config = config; + this.log = logProvider.getLog( getClass() ); } public ApplicationSupportedProtocols createSupportedRaftProtocol() { - List raftVersions = config.get( CausalClusteringSettings.raft_versions ); - return new ApplicationSupportedProtocols( Protocol.ApplicationProtocolCategory.RAFT, raftVersions ); + List configVersions = config.get( CausalClusteringSettings.raft_versions ); + if ( configVersions.isEmpty() ) + { + return new ApplicationSupportedProtocols( RAFT, Collections.emptyList() ); + } + else + { + List knownVersions = + protocolsForConfig( RAFT, configVersions, version -> Protocol.ApplicationProtocols.find( RAFT, version ) ); + if ( knownVersions.isEmpty() ) + { + throw new IllegalArgumentException( String.format( "None of configured Raft implementations %s are known", configVersions ) ); + } + else + { + return new ApplicationSupportedProtocols( RAFT, knownVersions ); + } + } } public List createSupportedModifierProtocols() @@ -57,20 +82,30 @@ public List createSupportedModifierProtocols() private ModifierSupportedProtocols compressionProtocolVersions() { - return modifierProtocolVersions( CausalClusteringSettings.compression_versions, Protocol.ModifierProtocolCategory.COMPRESSION ); + List implementations = protocolsForConfig( COMPRESSION, config.get( CausalClusteringSettings.compression_versions ), + implementation -> Protocol.ModifierProtocols.find( COMPRESSION, implementation ) ); + + return new ModifierSupportedProtocols( COMPRESSION, implementations ); } - private ModifierSupportedProtocols modifierProtocolVersions( - Setting> compressionVersions, Protocol.ModifierProtocolCategory identifier ) + private , T extends Protocol> List protocolsForConfig( Protocol.Category category, List implementations, + Function> finder ) { - List compressionAlgorithms = config.get( compressionVersions ); - List versions = compressionAlgorithms.stream() - .map( Protocol.ModifierProtocols::fromFriendlyName ) + return implementations.stream() + .map( impl -> Pair.of( impl, finder.apply( impl ) ) ) + .peek( protocolWithImplementation -> logUnknownProtocol( category, protocolWithImplementation ) ) + .map( Pair::other ) .flatMap( Streams::ofOptional ) - .filter( protocol -> Objects.equals( protocol.category(), identifier.canonicalName() ) ) - .map( Protocol.ModifierProtocols::implementation ) + .map( Protocol::implementation ) .collect( Collectors.toList() ); + } - return new ModifierSupportedProtocols( identifier, versions ); + private , T extends Protocol> void logUnknownProtocol( Protocol.Category category, + Pair> protocolWithImplementation ) + { + if ( !protocolWithImplementation.other().isPresent() ) + { + log.warn( "Configured %s protocol implementation %s unknown. Ignoring.", category, protocolWithImplementation.first() ); + } } } diff --git a/enterprise/causal-clustering/src/main/java/org/neo4j/causalclustering/protocol/Protocol.java b/enterprise/causal-clustering/src/main/java/org/neo4j/causalclustering/protocol/Protocol.java index 54b5b4be86640..f532eb102ba50 100644 --- a/enterprise/causal-clustering/src/main/java/org/neo4j/causalclustering/protocol/Protocol.java +++ b/enterprise/causal-clustering/src/main/java/org/neo4j/causalclustering/protocol/Protocol.java @@ -21,6 +21,7 @@ import java.util.Objects; import java.util.Optional; +import java.util.function.Function; import java.util.stream.Stream; public interface Protocol> @@ -29,6 +30,15 @@ public interface Protocol> IMPL implementation(); + static , T extends Protocol> Optional find( + T[] values, Category category, IMPL implementation, Function normalise ) + { + return Stream.of( values ) + .filter( protocol -> Objects.equals( protocol.category(), category.canonicalName() ) ) + .filter( protocol -> Objects.equals( normalise.apply( protocol.implementation() ), normalise.apply( implementation ) ) ) + .findFirst(); + } + interface Category { String canonicalName(); @@ -75,6 +85,11 @@ public Integer implementation() { return version; } + + public static Optional find( ApplicationProtocolCategory category, Integer version ) + { + return Protocol.find( ApplicationProtocols.values(), category, version, Function.identity() ); + } } interface ModifierProtocol extends Protocol @@ -126,11 +141,9 @@ public String category() return identifier.canonicalName(); } - public static Optional fromFriendlyName( String friendlyName ) + public static Optional find( ModifierProtocolCategory category, String friendlyName ) { - return Stream.of( ModifierProtocols.values() ) - .filter( protocol -> Objects.equals( protocol.friendlyName.toLowerCase(), friendlyName.toLowerCase() ) ) - .findFirst(); + return Protocol.find( ModifierProtocols.values(), category, friendlyName, String::toLowerCase ); } public static class Implementations diff --git a/enterprise/causal-clustering/src/test/java/org/neo4j/causalclustering/core/SupportedProtocolCreatorTest.java b/enterprise/causal-clustering/src/test/java/org/neo4j/causalclustering/core/SupportedProtocolCreatorTest.java index 0642d5542b070..d2771c6b4bb82 100644 --- a/enterprise/causal-clustering/src/test/java/org/neo4j/causalclustering/core/SupportedProtocolCreatorTest.java +++ b/enterprise/causal-clustering/src/test/java/org/neo4j/causalclustering/core/SupportedProtocolCreatorTest.java @@ -30,22 +30,27 @@ import org.neo4j.causalclustering.protocol.handshake.ModifierSupportedProtocols; import org.neo4j.causalclustering.protocol.handshake.SupportedProtocols; import org.neo4j.kernel.configuration.Config; +import org.neo4j.logging.NullLogProvider; import static org.hamcrest.Matchers.contains; import static org.hamcrest.Matchers.empty; import static org.hamcrest.Matchers.equalTo; import static org.junit.Assert.assertThat; +import static org.neo4j.causalclustering.protocol.Protocol.ModifierProtocols.COMPRESSION_SNAPPY; public class SupportedProtocolCreatorTest { + + private NullLogProvider log = NullLogProvider.getInstance(); + @Test - public void shouldReturnRAftProtocol() throws Throwable + public void shouldReturnRaftProtocol() throws Throwable { // given Config config = Config.defaults(); // when - ApplicationSupportedProtocols supportedRaftProtocol = new SupportedProtocolCreator( config ).createSupportedRaftProtocol(); + ApplicationSupportedProtocols supportedRaftProtocol = new SupportedProtocolCreator( config, log ).createSupportedRaftProtocol(); // then assertThat( supportedRaftProtocol.identifier(), equalTo( Protocol.ApplicationProtocolCategory.RAFT ) ); @@ -58,23 +63,49 @@ public void shouldReturnEmptyVersionSupportedRaftProtocolIfNoVersionsConfigured( Config config = Config.defaults(); // when - ApplicationSupportedProtocols supportedRaftProtocol = new SupportedProtocolCreator( config ).createSupportedRaftProtocol(); + ApplicationSupportedProtocols supportedRaftProtocol = new SupportedProtocolCreator( config, log ).createSupportedRaftProtocol(); // then assertThat( supportedRaftProtocol.versions(), empty() ); } + @Test + public void shouldFilterUnknownRaftImplementations() throws Throwable + { + // given + Config config = Config.defaults( CausalClusteringSettings.raft_versions, "1, 2, 3" ); + + // when + ApplicationSupportedProtocols supportedRaftProtocol = new SupportedProtocolCreator( config, log ).createSupportedRaftProtocol(); + + // then + assertThat( supportedRaftProtocol.versions(), contains( 1 ) ); + + } + @Test public void shouldReturnConfiguredRaftProtocolVersions() throws Throwable { // given - Config config = Config.defaults( CausalClusteringSettings.raft_versions, "2,3,1" ); + Config config = Config.defaults( CausalClusteringSettings.raft_versions, "1" ); // when - ApplicationSupportedProtocols supportedRaftProtocol = new SupportedProtocolCreator( config ).createSupportedRaftProtocol(); + ApplicationSupportedProtocols supportedRaftProtocol = new SupportedProtocolCreator( config, log ).createSupportedRaftProtocol(); // then - assertThat( supportedRaftProtocol.versions(), contains( 2,3,1 ) ); + assertThat( supportedRaftProtocol.versions(), contains( 1 ) ); + } + + @Test( expected = IllegalArgumentException.class ) + public void shouldThrowIfVersionsSpecifiedButAllUnknown() throws Throwable + { + // given + Config config = Config.defaults( CausalClusteringSettings.raft_versions, String.valueOf( Integer.MAX_VALUE ) ); + + // when + ApplicationSupportedProtocols supportedRaftProtocol = new SupportedProtocolCreator( config, log ).createSupportedRaftProtocol(); + + // then throw } @Test @@ -85,21 +116,21 @@ public void shouldNotReturnModifiersIfNoVersionsSpecified() throws Throwable // when List supportedModifierProtocols = - new SupportedProtocolCreator( config ).createSupportedModifierProtocols(); + new SupportedProtocolCreator( config, log ).createSupportedModifierProtocols(); // then assertThat( supportedModifierProtocols, empty() ); } @Test - public void shouldReturnCompressionIfVersionsSpecified() throws Throwable + public void shouldReturnACompressionModifierIfCompressionVersionsSpecified() throws Throwable { // given - Config config = Config.defaults( CausalClusteringSettings.compression_versions, "snappy" ); + Config config = Config.defaults( CausalClusteringSettings.compression_versions, COMPRESSION_SNAPPY.implementation() ); // when List supportedModifierProtocols = - new SupportedProtocolCreator( config ).createSupportedModifierProtocols(); + new SupportedProtocolCreator( config, log ).createSupportedModifierProtocols(); // then Stream> identifiers = supportedModifierProtocols.stream().map( SupportedProtocols::identifier ); @@ -107,17 +138,32 @@ public void shouldReturnCompressionIfVersionsSpecified() throws Throwable } @Test - public void shouldReturnCompressionVersionsSpecified() throws Throwable + public void shouldReturnCompressionWithVersionsSpecified() throws Throwable + { + // given + Config config = Config.defaults( CausalClusteringSettings.compression_versions, COMPRESSION_SNAPPY.implementation() ); + + // when + List supportedModifierProtocols = + new SupportedProtocolCreator( config, log ).createSupportedModifierProtocols(); + + // then + List versions = supportedModifierProtocols.get( 0 ).versions(); + assertThat( versions, contains( COMPRESSION_SNAPPY.implementation() ) ); + } + + @Test + public void shouldReturnCompressionWithVersionsSpecifiedCaseInsensitive() throws Throwable { // given - Config config = Config.defaults( CausalClusteringSettings.compression_versions, "snappy" ); + Config config = Config.defaults( CausalClusteringSettings.compression_versions, COMPRESSION_SNAPPY.implementation().toLowerCase() ); // when List supportedModifierProtocols = - new SupportedProtocolCreator( config ).createSupportedModifierProtocols(); + new SupportedProtocolCreator( config, log ).createSupportedModifierProtocols(); // then List versions = supportedModifierProtocols.get( 0 ).versions(); - assertThat( versions, contains( Protocol.ModifierProtocols.COMPRESSION_SNAPPY.implementation() ) ); + assertThat( versions, contains( COMPRESSION_SNAPPY.implementation() ) ); } }