diff --git a/enterprise/causal-clustering/src/main/java/org/neo4j/causalclustering/core/CausalClusterConfigurationValidator.java b/enterprise/causal-clustering/src/main/java/org/neo4j/causalclustering/core/CausalClusterConfigurationValidator.java index cd956df5fb03b..a8eb4b658c5f1 100644 --- a/enterprise/causal-clustering/src/main/java/org/neo4j/causalclustering/core/CausalClusterConfigurationValidator.java +++ b/enterprise/causal-clustering/src/main/java/org/neo4j/causalclustering/core/CausalClusterConfigurationValidator.java @@ -40,8 +40,7 @@ public class CausalClusterConfigurationValidator implements ConfigurationValidat @Override @Nonnull public Map validate( @Nonnull Collection settingValidators, - @Nonnull Map rawConfig, @Nonnull Log log, boolean parsingFile ) - throws InvalidSettingException + @Nonnull Map rawConfig, @Nonnull Log log, boolean parsingFile ) throws InvalidSettingException { // Make sure mode is CC Mode mode = ClusterSettings.mode.apply( rawConfig::get ); diff --git a/enterprise/causal-clustering/src/main/java/org/neo4j/causalclustering/core/CausalClusteringSettings.java b/enterprise/causal-clustering/src/main/java/org/neo4j/causalclustering/core/CausalClusteringSettings.java index ed20e4f637c63..7961309fd25f2 100644 --- a/enterprise/causal-clustering/src/main/java/org/neo4j/causalclustering/core/CausalClusteringSettings.java +++ b/enterprise/causal-clustering/src/main/java/org/neo4j/causalclustering/core/CausalClusteringSettings.java @@ -27,8 +27,6 @@ import java.util.function.Consumer; import java.util.function.Function; -import org.neo4j.causalclustering.discovery.NoOpResolutionResolver; -import org.neo4j.causalclustering.discovery.ResolutionResolver; import org.neo4j.configuration.Description; import org.neo4j.configuration.Internal; import org.neo4j.configuration.LoadableConfig; @@ -37,7 +35,6 @@ import org.neo4j.graphdb.config.Setting; import org.neo4j.helpers.AdvertisedSocketAddress; import org.neo4j.helpers.ListenSocketAddress; -import org.neo4j.kernel.configuration.Config; import org.neo4j.kernel.configuration.Settings; import static org.neo4j.kernel.configuration.Settings.ADVERTISED_SOCKET_ADDRESS; @@ -135,26 +132,14 @@ public enum DiscoveryType public static final Setting discovery_type = setting( "causal_clustering.discovery_type", options( DiscoveryType.class ), DiscoveryType.LIST.name() ); - public static ResolutionResolver chooseResolver( Config config ) - { - CausalClusteringSettings.DiscoveryType discoveryType = config.get( CausalClusteringSettings.discovery_type ); - if ( discoveryType == CausalClusteringSettings.DiscoveryType.DNS ) - { - return new NoOpResolutionResolver(); - } - else - { - return new NoOpResolutionResolver(); - } - } - @Description( "Prevents the network middleware from dumping its own logs. Defaults to true." ) public static final Setting disable_middleware_logging = setting( "causal_clustering.disable_middleware_logging", BOOLEAN, TRUE ); @Internal // not supported yet @Description( "Hazelcast license key" ) - public static final Setting hazelcast_license_key = setting( "hazelcast.license_key", STRING, NO_DEFAULT ); + public static final Setting hazelcast_license_key = + setting( "hazelcast.license_key", STRING, NO_DEFAULT ); @Description( "The maximum file size before the storage file is rotated (in unit of entries)" ) public static final Setting last_flushed_state_size = @@ -367,18 +352,18 @@ public static ResolutionResolver chooseResolver( Config config ) public static final Setting load_balancing_plugin = setting( "causal_clustering.load_balancing.plugin", STRING, "server_policies" ); - static BaseSetting prefixSetting( final String name, final Function parser, - final String defaultValue ) + static BaseSetting prefixSetting( final String name, final Function parser, + final String defaultValue ) { - BiFunction,String> valueLookup = ( n, settings ) -> settings.apply( n ); - BiFunction,String> defaultLookup = - determineDefaultLookup( defaultValue, valueLookup ); + BiFunction, String> valueLookup = ( n, settings ) -> settings.apply( n ); + BiFunction, String> defaultLookup = determineDefaultLookup( defaultValue, + valueLookup ); return new Settings.DefaultSetting( name, parser, valueLookup, defaultLookup ) { @Override - public Map validate( Map rawConfig, Consumer warningConsumer ) + public Map validate( Map rawConfig, Consumer warningConsumer ) throws InvalidSettingException { // Validate setting, if present or default value otherwise @@ -387,9 +372,10 @@ public Map validate( Map rawConfig, Consumer validConfig = new HashMap<>(); + Map validConfig = new HashMap<>(); - rawConfig.keySet().stream().filter( key -> key.startsWith( name() ) ) + rawConfig.keySet().stream() + .filter( key -> key.startsWith( name() ) ) .forEach( key -> validConfig.put( key, rawConfig.get( key ) ) ); return validConfig; @@ -402,9 +388,9 @@ public Map validate( Map rawConfig, Consumer load_balancing_config = prefixSetting( "causal_clustering.load_balancing.config", STRING, "" ); @@ -420,9 +406,8 @@ public Map validate( Map rawConfig, Consumer multi_dc_license = setting( "causal_clustering.multi_dc_license", BOOLEAN, FALSE ); - @Description( - "Name of the SSL policy to be used by the clustering, as defined under the dbms.ssl.policy.* settings." + - " If no policy is configured then the communication will not be secured." ) + @Description( "Name of the SSL policy to be used by the clustering, as defined under the dbms.ssl.policy.* settings." + + " If no policy is configured then the communication will not be secured." ) public static final Setting ssl_policy = prefixSetting( "causal_clustering.ssl_policy", STRING, NO_DEFAULT ); } diff --git a/enterprise/causal-clustering/src/main/java/org/neo4j/causalclustering/core/state/ClusteringModule.java b/enterprise/causal-clustering/src/main/java/org/neo4j/causalclustering/core/state/ClusteringModule.java index 2359528b538f0..619ebe857ba1b 100644 --- a/enterprise/causal-clustering/src/main/java/org/neo4j/causalclustering/core/state/ClusteringModule.java +++ b/enterprise/causal-clustering/src/main/java/org/neo4j/causalclustering/core/state/ClusteringModule.java @@ -41,8 +41,8 @@ import org.neo4j.time.Clocks; import static java.lang.Thread.sleep; -import static org.neo4j.causalclustering.core.CausalClusteringSettings.chooseResolver; import static org.neo4j.causalclustering.core.server.CoreServerModule.CLUSTER_ID_NAME; +import static org.neo4j.causalclustering.discovery.ResolutionResolverFactory.chooseResolver; public class ClusteringModule { @@ -58,7 +58,7 @@ public ClusteringModule( DiscoveryServiceFactory discoveryServiceFactory, Member LogProvider userLogProvider = platformModule.logging.getUserLogProvider(); Dependencies dependencies = platformModule.dependencies; FileSystemAbstraction fileSystem = platformModule.fileSystem; - ResolutionResolver resolutionResolver = chooseResolver( config ); + ResolutionResolver resolutionResolver = chooseResolver( config, logProvider, userLogProvider ); topologyService = discoveryServiceFactory .coreTopologyService( config, sslPolicy, myself, platformModule.jobScheduler, logProvider, @@ -73,8 +73,7 @@ public ClusteringModule( DiscoveryServiceFactory discoveryServiceFactory, Member logProvider ); CoreBootstrapper coreBootstrapper = - new CoreBootstrapper( platformModule.storeDir, platformModule.pageCache, fileSystem, config, - logProvider ); + new CoreBootstrapper( platformModule.storeDir, platformModule.pageCache, fileSystem, config, logProvider ); clusterBinder = new ClusterBinder( clusterIdStorage, topologyService, logProvider, Clocks.systemClock(), () -> sleep( 100 ), 300_000, coreBootstrapper ); diff --git a/enterprise/causal-clustering/src/main/java/org/neo4j/causalclustering/discovery/DnsResolutionResolver.java b/enterprise/causal-clustering/src/main/java/org/neo4j/causalclustering/discovery/DnsResolutionResolver.java new file mode 100644 index 0000000000000..286d22c8faed8 --- /dev/null +++ b/enterprise/causal-clustering/src/main/java/org/neo4j/causalclustering/discovery/DnsResolutionResolver.java @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2002-2017 "Neo Technology," + * Network Engine for Objects in Lund AB [http://neotechnology.com] + * + * This file is part of Neo4j. + * + * Neo4j is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ +package org.neo4j.causalclustering.discovery; + +import java.net.InetAddress; +import java.net.UnknownHostException; +import java.util.Collection; +import java.util.HashSet; +import java.util.Set; + +import org.neo4j.helpers.AdvertisedSocketAddress; +import org.neo4j.logging.Log; +import org.neo4j.logging.LogProvider; + +import static java.lang.String.format; + +public class DnsResolutionResolver implements ResolutionResolver +{ + private final Log userLog; + private final Log log; + private final DomainNameResolver domainNameResolver; + + public DnsResolutionResolver( LogProvider logProvider, LogProvider userLogProvider, + DomainNameResolver domainNameResolver ) + { + log = logProvider.getLog( getClass() ); + userLog = userLogProvider.getLog( getClass() ); + this.domainNameResolver = domainNameResolver; + } + + @Override + public Collection resolve( AdvertisedSocketAddress initialAddress ) + { + Set addresses = new HashSet<>(); + try + { + InetAddress[] ipAddresses = domainNameResolver.resolveDomainName( initialAddress.getHostname() ); + + for ( InetAddress ipAddress : ipAddresses ) + { + addresses.add( new AdvertisedSocketAddress( ipAddress.getHostAddress(), initialAddress.getPort() ) ); + } + + userLog.info( "Resolved initial host '%s' to %s", initialAddress, addresses ); + return addresses; + } + catch ( UnknownHostException e ) + { + log.error( format( "Failed to resolve host `%s` to IPs due to error: %s", initialAddress, e.getMessage() ), e ); + + addresses.add( initialAddress ); + return addresses; + } + } +} diff --git a/enterprise/causal-clustering/src/main/java/org/neo4j/causalclustering/discovery/DomainNameResolver.java b/enterprise/causal-clustering/src/main/java/org/neo4j/causalclustering/discovery/DomainNameResolver.java new file mode 100644 index 0000000000000..fd26fce78518e --- /dev/null +++ b/enterprise/causal-clustering/src/main/java/org/neo4j/causalclustering/discovery/DomainNameResolver.java @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2002-2017 "Neo Technology," + * Network Engine for Objects in Lund AB [http://neotechnology.com] + * + * This file is part of Neo4j. + * + * Neo4j is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ +package org.neo4j.causalclustering.discovery; + +import java.net.InetAddress; +import java.net.UnknownHostException; + +public interface DomainNameResolver +{ + InetAddress[] resolveDomainName(String hostname) throws UnknownHostException; +} diff --git a/enterprise/causal-clustering/src/main/java/org/neo4j/causalclustering/discovery/DomainNameResolverImpl.java b/enterprise/causal-clustering/src/main/java/org/neo4j/causalclustering/discovery/DomainNameResolverImpl.java new file mode 100644 index 0000000000000..fe969178d71c6 --- /dev/null +++ b/enterprise/causal-clustering/src/main/java/org/neo4j/causalclustering/discovery/DomainNameResolverImpl.java @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2002-2017 "Neo Technology," + * Network Engine for Objects in Lund AB [http://neotechnology.com] + * + * This file is part of Neo4j. + * + * Neo4j is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ +package org.neo4j.causalclustering.discovery; + +import java.net.InetAddress; +import java.net.UnknownHostException; + +public class DomainNameResolverImpl implements DomainNameResolver +{ + public InetAddress[] resolveDomainName(String hostname) throws UnknownHostException + { + return InetAddress.getAllByName( hostname ); + } +} diff --git a/enterprise/causal-clustering/src/main/java/org/neo4j/causalclustering/discovery/HazelcastClientConnector.java b/enterprise/causal-clustering/src/main/java/org/neo4j/causalclustering/discovery/HazelcastClientConnector.java index 7aad549028087..19a2a3b802cf5 100644 --- a/enterprise/causal-clustering/src/main/java/org/neo4j/causalclustering/discovery/HazelcastClientConnector.java +++ b/enterprise/causal-clustering/src/main/java/org/neo4j/causalclustering/discovery/HazelcastClientConnector.java @@ -55,10 +55,12 @@ public HazelcastInstance connectToHazelcast() ClientNetworkConfig networkConfig = clientConfig.getNetworkConfig(); - for ( AdvertisedSocketAddress address : resolutionResolver - .resolve( config.get( CausalClusteringSettings.initial_discovery_members ) ) ) + for ( AdvertisedSocketAddress address : config.get( CausalClusteringSettings.initial_discovery_members ) ) { - networkConfig.addAddress( address.toString() ); + for ( AdvertisedSocketAddress advertisedSocketAddress : resolutionResolver.resolve( address ) ) + { + networkConfig.addAddress( advertisedSocketAddress.toString() ); + } } configureSsl( networkConfig, sslPolicy, logProvider ); diff --git a/enterprise/causal-clustering/src/main/java/org/neo4j/causalclustering/discovery/HazelcastCoreTopologyService.java b/enterprise/causal-clustering/src/main/java/org/neo4j/causalclustering/discovery/HazelcastCoreTopologyService.java index ed62c54d7d830..c78d79f38a5c5 100644 --- a/enterprise/causal-clustering/src/main/java/org/neo4j/causalclustering/discovery/HazelcastCoreTopologyService.java +++ b/enterprise/causal-clustering/src/main/java/org/neo4j/causalclustering/discovery/HazelcastCoreTopologyService.java @@ -19,8 +19,23 @@ */ package org.neo4j.causalclustering.discovery; -import com.hazelcast.config.*; -import com.hazelcast.core.*; +import com.hazelcast.config.InterfacesConfig; +import com.hazelcast.config.JoinConfig; +import com.hazelcast.config.MemberAttributeConfig; +import com.hazelcast.config.NetworkConfig; +import com.hazelcast.config.TcpIpConfig; +import com.hazelcast.core.Hazelcast; +import com.hazelcast.core.HazelcastException; +import com.hazelcast.core.HazelcastInstance; +import com.hazelcast.core.MemberAttributeEvent; +import com.hazelcast.core.MembershipEvent; +import com.hazelcast.core.MembershipListener; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.concurrent.TimeUnit; import org.neo4j.causalclustering.core.CausalClusteringSettings; import org.neo4j.causalclustering.helper.RobustJobSchedulerWrapper; @@ -49,15 +64,6 @@ import static org.neo4j.causalclustering.discovery.HazelcastClusterTopology.getCoreTopology; import static org.neo4j.causalclustering.discovery.HazelcastClusterTopology.getReadReplicaTopology; import static org.neo4j.causalclustering.discovery.HazelcastClusterTopology.refreshGroups; - -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Optional; -import java.util.concurrent.TimeUnit; - -import static com.hazelcast.spi.properties.GroupProperty.*; -import static org.neo4j.causalclustering.discovery.HazelcastClusterTopology.*; import static org.neo4j.causalclustering.discovery.HazelcastSslConfiguration.configureSsl; class HazelcastCoreTopologyService extends LifecycleAdapter implements CoreTopologyService @@ -135,10 +141,8 @@ public void start() throws Throwable { return; } - membershipRegistrationId = - hazelcastInstance.getCluster().addMembershipListener( new OurMembershipListener() ); - refreshJob = scheduler.scheduleRecurring( "TopologyRefresh", refreshPeriod, - HazelcastCoreTopologyService.this::refreshTopology ); + membershipRegistrationId = hazelcastInstance.getCluster().addMembershipListener( new OurMembershipListener() ); + refreshJob = scheduler.scheduleRecurring( "TopologyRefresh", refreshPeriod, HazelcastCoreTopologyService.this::refreshTopology ); log.info( "Cluster discovery service started" ); } ); startingThread.setDaemon( true ); @@ -186,9 +190,12 @@ private HazelcastInstance createHazelcastInstance() tcpIpConfig.setEnabled( true ); List initialMembers = config.get( initial_discovery_members ); - for ( AdvertisedSocketAddress advertisedAddress : resolutionResolver.resolve( initialMembers ) ) + for ( AdvertisedSocketAddress address : initialMembers ) { - tcpIpConfig.addMember( advertisedAddress.toString() ); + for ( AdvertisedSocketAddress advertisedSocketAddress : resolutionResolver.resolve( address ) ) + { + tcpIpConfig.addMember( advertisedSocketAddress.toString() ); + } } ListenSocketAddress hazelcastAddress = config.get( discovery_listen_address ); @@ -238,8 +245,7 @@ private HazelcastInstance createHazelcastInstance() c.setNetworkConfig( networkConfig ); - MemberAttributeConfig memberAttributeConfig = - HazelcastClusterTopology.buildMemberAttributesForCore( myself, config ); + MemberAttributeConfig memberAttributeConfig = HazelcastClusterTopology.buildMemberAttributesForCore( myself, config ); c.setMemberAttributeConfig( memberAttributeConfig ); logConnectionInfo( initialMembers ); diff --git a/enterprise/causal-clustering/src/main/java/org/neo4j/causalclustering/discovery/MapDomainNameResolver.java b/enterprise/causal-clustering/src/main/java/org/neo4j/causalclustering/discovery/MapDomainNameResolver.java new file mode 100644 index 0000000000000..07887ce49ec38 --- /dev/null +++ b/enterprise/causal-clustering/src/main/java/org/neo4j/causalclustering/discovery/MapDomainNameResolver.java @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2002-2017 "Neo Technology," + * Network Engine for Objects in Lund AB [http://neotechnology.com] + * + * This file is part of Neo4j. + * + * Neo4j is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ +package org.neo4j.causalclustering.discovery; + +import java.net.InetAddress; +import java.net.UnknownHostException; +import java.util.Collection; +import java.util.Map; +import java.util.stream.Collectors; + +public class MapDomainNameResolver implements DomainNameResolver +{ + private final Map domainNameMapping; + + public MapDomainNameResolver( Map mapping ) + { + domainNameMapping = mapping; + } + + @Override + public InetAddress[] resolveDomainName( String hostname ) throws UnknownHostException + { + if ( domainNameMapping.containsKey( hostname ) ) + { + return domainNameMapping.get( hostname ); + } + throw new UnknownHostException(hostname); + } + + public void setHostnameAddresses( String hostname, Collection addresses ) + { + InetAddress[] processedAddresses = new InetAddress[addresses.size()]; + addresses.stream().map( MapDomainNameResolver::inetAddress ).collect( Collectors.toList() ) + .toArray( processedAddresses ); + domainNameMapping.put( hostname, processedAddresses ); + } + + private static InetAddress inetAddress( String address ) + { + try + { + return InetAddress.getByName( address ); + } + catch ( UnknownHostException e ) + { + throw new RuntimeException( e ); + } + } +} diff --git a/enterprise/causal-clustering/src/main/java/org/neo4j/causalclustering/discovery/NoOpResolutionResolver.java b/enterprise/causal-clustering/src/main/java/org/neo4j/causalclustering/discovery/NoOpResolutionResolver.java index 1e9ee557ff565..fb1b90c859bc1 100644 --- a/enterprise/causal-clustering/src/main/java/org/neo4j/causalclustering/discovery/NoOpResolutionResolver.java +++ b/enterprise/causal-clustering/src/main/java/org/neo4j/causalclustering/discovery/NoOpResolutionResolver.java @@ -23,11 +23,13 @@ import org.neo4j.helpers.AdvertisedSocketAddress; +import static java.util.Collections.singleton; + public class NoOpResolutionResolver implements ResolutionResolver { @Override - public Collection resolve( Collection advertisedSocketAddresses ) + public Collection resolve( AdvertisedSocketAddress advertisedSocketAddresses ) { - return advertisedSocketAddresses; + return singleton(advertisedSocketAddresses); } } diff --git a/enterprise/causal-clustering/src/main/java/org/neo4j/causalclustering/discovery/ResolutionResolver.java b/enterprise/causal-clustering/src/main/java/org/neo4j/causalclustering/discovery/ResolutionResolver.java index 04f54a678c3a1..61ee114b3608b 100644 --- a/enterprise/causal-clustering/src/main/java/org/neo4j/causalclustering/discovery/ResolutionResolver.java +++ b/enterprise/causal-clustering/src/main/java/org/neo4j/causalclustering/discovery/ResolutionResolver.java @@ -25,5 +25,5 @@ public interface ResolutionResolver { - Collection resolve( Collection advertisedSocketAddresses ); + Collection resolve( AdvertisedSocketAddress advertisedSocketAddresses ); } diff --git a/enterprise/causal-clustering/src/main/java/org/neo4j/causalclustering/discovery/ResolutionResolverFactory.java b/enterprise/causal-clustering/src/main/java/org/neo4j/causalclustering/discovery/ResolutionResolverFactory.java new file mode 100644 index 0000000000000..cfa09c4f1d449 --- /dev/null +++ b/enterprise/causal-clustering/src/main/java/org/neo4j/causalclustering/discovery/ResolutionResolverFactory.java @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2002-2017 "Neo Technology," + * Network Engine for Objects in Lund AB [http://neotechnology.com] + * + * This file is part of Neo4j. + * + * Neo4j is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ +package org.neo4j.causalclustering.discovery; + +import org.neo4j.causalclustering.core.CausalClusteringSettings; +import org.neo4j.kernel.configuration.Config; +import org.neo4j.logging.LogProvider; + +public class ResolutionResolverFactory +{ + public static ResolutionResolver chooseResolver( Config config, LogProvider logProvider, + LogProvider userLogProvider ) + { + CausalClusteringSettings.DiscoveryType discoveryType = config.get( CausalClusteringSettings.discovery_type ); + if ( discoveryType == CausalClusteringSettings.DiscoveryType.DNS ) + { + return new DnsResolutionResolver( logProvider, userLogProvider, new DomainNameResolverImpl() ); + } + else + { + return new NoOpResolutionResolver(); + } + } +} diff --git a/enterprise/causal-clustering/src/main/java/org/neo4j/causalclustering/readreplica/EnterpriseReadReplicaEditionModule.java b/enterprise/causal-clustering/src/main/java/org/neo4j/causalclustering/readreplica/EnterpriseReadReplicaEditionModule.java index 4f5d44e16ffe6..1c0dc99651440 100644 --- a/enterprise/causal-clustering/src/main/java/org/neo4j/causalclustering/readreplica/EnterpriseReadReplicaEditionModule.java +++ b/enterprise/causal-clustering/src/main/java/org/neo4j/causalclustering/readreplica/EnterpriseReadReplicaEditionModule.java @@ -105,7 +105,7 @@ import org.neo4j.time.Clocks; import org.neo4j.udc.UsageData; -import static org.neo4j.causalclustering.core.CausalClusteringSettings.chooseResolver; +import static org.neo4j.causalclustering.discovery.ResolutionResolverFactory.chooseResolver; import static org.neo4j.kernel.impl.factory.CommunityEditionModule.createLockManager; /** @@ -133,8 +133,8 @@ public class EnterpriseReadReplicaEditionModule extends EditionModule this.accessCapability = new ReadOnly(); - watcherService = createFileSystemWatcherService( fileSystem, storeDir, logging, platformModule.jobScheduler, - fileWatcherFileNameFilter() ); + watcherService = createFileSystemWatcherService( fileSystem, storeDir, logging, + platformModule.jobScheduler, fileWatcherFileNameFilter() ); dependencies.satisfyDependencies( watcherService ); GraphDatabaseFacade graphDatabaseFacade = platformModule.graphDatabaseFacade; @@ -180,25 +180,23 @@ public class EnterpriseReadReplicaEditionModule extends EditionModule commitProcessFactory = readOnly(); LogProvider logProvider = platformModule.logging.getInternalLogProvider(); + LogProvider userLogProvider = platformModule.logging.getUserLogProvider(); logProvider.getLog( getClass() ).info( String.format( "Generated new id: %s", myself ) ); - SslPolicyLoader sslPolicyFactory = - dependencies.satisfyDependency( SslPolicyLoader.create( config, logProvider ) ); + SslPolicyLoader sslPolicyFactory = dependencies.satisfyDependency( SslPolicyLoader.create( config, logProvider ) ); SslPolicy clusterSslPolicy = sslPolicyFactory.getPolicy( config.get( CausalClusteringSettings.ssl_policy ) ); - ResolutionResolver resolutionResolver = chooseResolver( config ); + ResolutionResolver resolutionResolver = chooseResolver( config, logProvider, userLogProvider ); - TopologyService topologyService = discoveryServiceFactory - .topologyService( config, clusterSslPolicy, logProvider, platformModule.jobScheduler, myself, - resolutionResolver ); + TopologyService topologyService = discoveryServiceFactory.topologyService( config, clusterSslPolicy, + logProvider, platformModule.jobScheduler, myself, resolutionResolver ); life.add( dependencies.satisfyDependency( topologyService ) ); - long inactivityTimeoutMillis = - config.get( CausalClusteringSettings.catch_up_client_inactivity_timeout ).toMillis(); + long inactivityTimeoutMillis = config.get( CausalClusteringSettings.catch_up_client_inactivity_timeout ).toMillis(); CatchUpClient catchUpClient = life.add( - new CatchUpClient( topologyService, logProvider, Clocks.systemClock(), inactivityTimeoutMillis, - monitors, clusterSslPolicy ) ); + new CatchUpClient( topologyService, logProvider, Clocks.systemClock(), + inactivityTimeoutMillis, monitors, clusterSslPolicy ) ); final Supplier databaseHealthSupplier = dependencies.provideDependency( DatabaseHealth.class ); @@ -219,7 +217,8 @@ public class EnterpriseReadReplicaEditionModule extends EditionModule LocalDatabase localDatabase = new LocalDatabase( platformModule.storeDir, storeFiles, platformModule.dataSourceManager, - databaseHealthSupplier, watcherService, platformModule.availabilityGuard, logProvider ); + databaseHealthSupplier, watcherService, platformModule.availabilityGuard, + logProvider ); RemoteStore remoteStore = new RemoteStore( platformModule.logging.getInternalLogProvider(), fileSystem, platformModule.pageCache, @@ -314,7 +313,8 @@ private OnlineBackupKernelExtension pickBackupExtension( NeoStoreDataSource data static Predicate fileWatcherFileNameFilter() { - return Predicates.any( fileName -> fileName.startsWith( PhysicalLogFile.DEFAULT_NAME ), + return Predicates.any( + fileName -> fileName.startsWith( PhysicalLogFile.DEFAULT_NAME ), fileName -> fileName.startsWith( IndexConfigStore.INDEX_DB_FILE_NAME ), filename -> filename.startsWith( StoreUtil.BRANCH_SUBDIRECTORY ), filename -> filename.startsWith( StoreUtil.TEMP_COPY_DIRECTORY_NAME ) ); diff --git a/enterprise/causal-clustering/src/test/java/org/neo4j/causalclustering/core/consensus/shipping/RaftLogShipperTest.java b/enterprise/causal-clustering/src/test/java/org/neo4j/causalclustering/core/consensus/shipping/RaftLogShipperTest.java index f8d09889972b3..a86af05025dbd 100644 --- a/enterprise/causal-clustering/src/test/java/org/neo4j/causalclustering/core/consensus/shipping/RaftLogShipperTest.java +++ b/enterprise/causal-clustering/src/test/java/org/neo4j/causalclustering/core/consensus/shipping/RaftLogShipperTest.java @@ -340,12 +340,12 @@ public void shouldPickUpAfterMissedBatch() throws Exception startLogShipper(); logShipper.onMatch( 0, new LeaderContext( 0, 0 ) ); - // we are now in PIPELINE discoveryType, because we matched and the entire last batch was sent out + // we are now in PIPELINE mode, because we matched and the entire last batch was sent out logShipper.onTimeout(); - // and now we should be in CATCHUP discoveryType, awaiting a late response + // and now we should be in CATCHUP mode, awaiting a late response - // the response to the batch never came, so on timeout we enter MISMATCH discoveryType and send a single entry based on the latest we knowingly sent (entry3) + // the response to the batch never came, so on timeout we enter MISMATCH mode and send a single entry based on the latest we knowingly sent (entry3) logShipper.onTimeout(); outbound.clear(); diff --git a/enterprise/causal-clustering/src/test/java/org/neo4j/causalclustering/discovery/DnsResolutionResolverTest.java b/enterprise/causal-clustering/src/test/java/org/neo4j/causalclustering/discovery/DnsResolutionResolverTest.java new file mode 100644 index 0000000000000..8b048626a7dc7 --- /dev/null +++ b/enterprise/causal-clustering/src/test/java/org/neo4j/causalclustering/discovery/DnsResolutionResolverTest.java @@ -0,0 +1,100 @@ +/* + * Copyright (c) 2002-2017 "Neo Technology," + * Network Engine for Objects in Lund AB [http://neotechnology.com] + * + * This file is part of Neo4j. + * + * Neo4j is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ +package org.neo4j.causalclustering.discovery; + +import org.junit.Test; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.List; + +import org.neo4j.helpers.AdvertisedSocketAddress; +import org.neo4j.logging.AssertableLogProvider; + +import static java.util.Arrays.asList; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +public class DnsResolutionResolverTest +{ + MapDomainNameResolver mockDomainNameResolver = new MapDomainNameResolver( new HashMap<>() ); + AssertableLogProvider logProvider = new AssertableLogProvider(); + AssertableLogProvider userLogProvider = new AssertableLogProvider(); + + private DnsResolutionResolver resolver = + new DnsResolutionResolver( logProvider, userLogProvider, mockDomainNameResolver ); + + @Test + public void hostnamesAreResolvedByTheResolver() + { + // given + mockDomainNameResolver.setHostnameAddresses( "google.com", asList( "1.2.3.4", "5.6.7.8" ) ); + + // when + Collection resolvedAddresses = + resolver.resolve( new AdvertisedSocketAddress( "google.com", 80 ) ); + + // then + assertEquals( 2, resolvedAddresses.size() ); + assertTrue( resolvedAddresses.removeIf( address -> address.getHostname().equals( "1.2.3.4" ) ) ); + assertTrue( resolvedAddresses.removeIf( address -> address.getHostname().equals( "5.6.7.8" ) ) ); + } + + @Test + public void resolvedHostnamesUseTheSamePort() + { + // given + mockDomainNameResolver.setHostnameAddresses( "google.com", asList( "1.2.3.4", "5.6.7.8" ) ); + + // when + List resolvedAddresses = + new ArrayList<>( resolver.resolve( new AdvertisedSocketAddress( "google.com", 1234 ) ) ); + + // then + assertEquals( 2, resolvedAddresses.size() ); + assertEquals( 1234, resolvedAddresses.get( 0 ).getPort() ); + assertEquals( 1234, resolvedAddresses.get( 1 ).getPort() ); + } + + @Test + public void resolutionDetailsAreLoggedToUserLogs() + { + // given + mockDomainNameResolver.setHostnameAddresses( "google.com", asList( "1.2.3.4", "5.6.7.8" ) ); + + // when + resolver.resolve( new AdvertisedSocketAddress( "google.com", 1234 ) ); + + // then + userLogProvider.assertContainsMessageContaining( "Resolved initial host '%s' to %s" ); + } + + @Test + public void unknownHostExceptionsAreLoggedAsErrors() + { + // when + resolver.resolve( new AdvertisedSocketAddress( "google.com", 1234 ) ); + + // then + logProvider.assertContainsMessageContaining( + "Failed to resolve host `google.com:1234` to IPs due to error: google.com" ); + } +} diff --git a/enterprise/causal-clustering/src/test/java/org/neo4j/causalclustering/discovery/ReadReplica.java b/enterprise/causal-clustering/src/test/java/org/neo4j/causalclustering/discovery/ReadReplica.java index d794159c4b23c..029514b846cdd 100644 --- a/enterprise/causal-clustering/src/test/java/org/neo4j/causalclustering/discovery/ReadReplica.java +++ b/enterprise/causal-clustering/src/test/java/org/neo4j/causalclustering/discovery/ReadReplica.java @@ -71,7 +71,7 @@ public ReadReplica( File parentDir, int serverId, DiscoveryServiceFactory discov .collect( joining( "," ) ); boltAdvertisedSocketAddress = advertisedAddress( advertisedAddress, boltPort ); - config.put( "dbms.discovery_type", "READ_REPLICA" ); + config.put( "dbms.mode", "READ_REPLICA" ); config.put( CausalClusteringSettings.initial_discovery_members.name(), initialHosts ); config.put( GraphDatabaseSettings.store_internal_log_level.name(), Level.DEBUG.name() ); config.put( GraphDatabaseSettings.record_format.name(), recordFormat ); diff --git a/enterprise/causal-clustering/src/test/java/org/neo4j/causalclustering/discovery/SharedDiscoveryService.java b/enterprise/causal-clustering/src/test/java/org/neo4j/causalclustering/discovery/SharedDiscoveryService.java index 9ecbc5da2030a..df0047d4aad50 100644 --- a/enterprise/causal-clustering/src/test/java/org/neo4j/causalclustering/discovery/SharedDiscoveryService.java +++ b/enterprise/causal-clustering/src/test/java/org/neo4j/causalclustering/discovery/SharedDiscoveryService.java @@ -19,13 +19,6 @@ */ package org.neo4j.causalclustering.discovery; -import org.neo4j.causalclustering.identity.ClusterId; -import org.neo4j.causalclustering.identity.MemberId; -import org.neo4j.kernel.configuration.Config; -import org.neo4j.kernel.impl.util.JobScheduler; -import org.neo4j.logging.LogProvider; -import org.neo4j.ssl.SslPolicy; - import java.util.ArrayList; import java.util.HashMap; import java.util.List; @@ -35,6 +28,13 @@ import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; +import org.neo4j.causalclustering.identity.ClusterId; +import org.neo4j.causalclustering.identity.MemberId; +import org.neo4j.kernel.configuration.Config; +import org.neo4j.kernel.impl.util.JobScheduler; +import org.neo4j.logging.LogProvider; +import org.neo4j.ssl.SslPolicy; + import static java.util.Collections.unmodifiableMap; public class SharedDiscoveryService implements DiscoveryServiceFactory @@ -49,7 +49,7 @@ public class SharedDiscoveryService implements DiscoveryServiceFactory @Override public CoreTopologyService coreTopologyService( Config config, SslPolicy sslPolicy, MemberId myself, JobScheduler jobScheduler, - LogProvider logProvider, LogProvider userLogProvider, ResolutionResolver resolutionResolver) + LogProvider logProvider, LogProvider userLogProvider, ResolutionResolver resolutionResolver ) { SharedDiscoveryCoreClient sharedDiscoveryCoreClient = new SharedDiscoveryCoreClient( this, myself, logProvider, config ); @@ -59,7 +59,8 @@ public CoreTopologyService coreTopologyService( Config config, SslPolicy sslPoli } @Override - public TopologyService topologyService( Config config, SslPolicy sslPolicy, LogProvider logProvider, JobScheduler jobScheduler, MemberId myself ) + public TopologyService topologyService( Config config, SslPolicy sslPolicy, LogProvider logProvider, + JobScheduler jobScheduler, MemberId myself, ResolutionResolver resolutionResolver ) { return new SharedDiscoveryReadReplicaClient( this, config, myself, logProvider ); } diff --git a/enterprise/causal-clustering/src/test/java/org/neo4j/causalclustering/discovery/SharedDiscoveryServiceIT.java b/enterprise/causal-clustering/src/test/java/org/neo4j/causalclustering/discovery/SharedDiscoveryServiceIT.java index 8cefa37109091..000baeb8a5367 100644 --- a/enterprise/causal-clustering/src/test/java/org/neo4j/causalclustering/discovery/SharedDiscoveryServiceIT.java +++ b/enterprise/causal-clustering/src/test/java/org/neo4j/causalclustering/discovery/SharedDiscoveryServiceIT.java @@ -21,6 +21,18 @@ import org.junit.Test; import org.mockito.ArgumentCaptor; + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.UUID; +import java.util.concurrent.Callable; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.Future; + import org.neo4j.causalclustering.core.CausalClusteringSettings; import org.neo4j.causalclustering.core.consensus.RaftMachine; import org.neo4j.causalclustering.identity.MemberId; @@ -29,20 +41,19 @@ import org.neo4j.kernel.impl.util.Neo4jJobScheduler; import org.neo4j.logging.NullLogProvider; -import java.util.*; -import java.util.concurrent.*; - import static java.util.concurrent.TimeUnit.MILLISECONDS; import static org.hamcrest.Matchers.equalTo; import static org.junit.Assert.fail; -import static org.mockito.Mockito.*; +import static org.mockito.Mockito.atLeastOnce; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; import static org.neo4j.helpers.collection.MapUtil.stringMap; import static org.neo4j.test.assertion.Assert.assertEventually; public class SharedDiscoveryServiceIT { private static final long TIMEOUT_MS = 15_000; - private static final long RUN_TIME_MS = 1000;; + private static final long RUN_TIME_MS = 1000; private NullLogProvider logProvider = NullLogProvider.getInstance(); private NullLogProvider userLogProvider = NullLogProvider.getInstance(); @@ -78,21 +89,23 @@ public void shouldDiscoverCompleteTargetSetWithoutDeadlocks() throws Exception } } - private Callable createDiscoveryJob( MemberId member, DiscoveryServiceFactory disoveryServiceFactory, Set expectedTargetSet ) throws ExecutionException, InterruptedException + private Callable createDiscoveryJob( MemberId member, DiscoveryServiceFactory disoveryServiceFactory, + Set expectedTargetSet ) throws ExecutionException, InterruptedException { Neo4jJobScheduler jobScheduler = new Neo4jJobScheduler(); jobScheduler.init(); ResolutionResolver resolutionResolver = new NoOpResolutionResolver(); - CoreTopologyService topologyService = disoveryServiceFactory.coreTopologyService( config(), null, member, - jobScheduler, logProvider, userLogProvider, resolutionResolver); + CoreTopologyService topologyService = disoveryServiceFactory + .coreTopologyService( config(), null, member, jobScheduler, logProvider, userLogProvider, + resolutionResolver ); return sharedClientStarter( topologyService, expectedTargetSet ); } private Config config() { return Config.embeddedDefaults( stringMap( - CausalClusteringSettings.raft_advertised_address.name(), "127.0.0.1:7000", + CausalClusteringSettings.raft_advertised_address.name(), "127.0.0.1:7000", CausalClusteringSettings.transaction_advertised_address.name(), "127.0.0.1:7001", new BoltConnector( "bolt" ).enabled.name(), "true", new BoltConnector( "bolt" ).advertised_address.name(), "127.0.0.1:7002" ) ); diff --git a/enterprise/metrics/src/main/java/org/neo4j/metrics/MetricsSettings.java b/enterprise/metrics/src/main/java/org/neo4j/metrics/MetricsSettings.java index a63a43244f580..b5ba6e32a3dce 100644 --- a/enterprise/metrics/src/main/java/org/neo4j/metrics/MetricsSettings.java +++ b/enterprise/metrics/src/main/java/org/neo4j/metrics/MetricsSettings.java @@ -66,7 +66,7 @@ public class MetricsSettings implements LoadableConfig @Description( "Enable reporting metrics about the network usage." ) public static Setting neoNetworkEnabled = setting( "metrics.neo4j.network.enabled", Settings.BOOLEAN, neoEnabled ); - @Description( "Enable reporting metrics about Causal Clustering discovery_type." ) + @Description( "Enable reporting metrics about Causal Clustering mode." ) public static Setting causalClusteringEnabled = setting( "metrics.neo4j.causal_clustering.enabled", Settings.BOOLEAN, neoEnabled ); @Description( "Enable reporting metrics about Neo4j check pointing; when it occurs and how much time it takes to " + diff --git a/enterprise/metrics/src/main/java/org/neo4j/metrics/source/Neo4jMetricsBuilder.java b/enterprise/metrics/src/main/java/org/neo4j/metrics/source/Neo4jMetricsBuilder.java index 0b42d92048c18..6b18d61759ba9 100644 --- a/enterprise/metrics/src/main/java/org/neo4j/metrics/source/Neo4jMetricsBuilder.java +++ b/enterprise/metrics/src/main/java/org/neo4j/metrics/source/Neo4jMetricsBuilder.java @@ -152,7 +152,7 @@ public boolean build() else { logService.getUserLog( getClass() ) - .warn( "Cluster metrics was enabled but the graph database is not in HA discovery_type." ); + .warn( "Cluster metrics was enabled but the graph database is not in HA mode." ); } } @@ -211,7 +211,7 @@ else if ( mode == OperationalMode.read_replica ) { logService.getUserLog( getClass() ) .warn( "Causal Clustering metrics was enabled but the graph database is not in Causal " + - "Clustering discovery_type." ); + "Clustering mode." ); } } diff --git a/enterprise/server-enterprise/src/main/java/org/neo4j/server/enterprise/EnterpriseNeoServer.java b/enterprise/server-enterprise/src/main/java/org/neo4j/server/enterprise/EnterpriseNeoServer.java index 23273e3bd7940..2aace260441be 100644 --- a/enterprise/server-enterprise/src/main/java/org/neo4j/server/enterprise/EnterpriseNeoServer.java +++ b/enterprise/server-enterprise/src/main/java/org/neo4j/server/enterprise/EnterpriseNeoServer.java @@ -100,8 +100,8 @@ protected static Database.Factory createDbFactory( Config config ) case HA: return lifecycleManagingDatabase( HA_FACTORY ); case ARBITER: - // Should never reach here because this discovery_type is handled separately by the scripts. - throw new IllegalArgumentException( "The server cannot be started in ARBITER discovery_type." ); + // Should never reach here because this mode is handled separately by the scripts. + throw new IllegalArgumentException( "The server cannot be started in ARBITER mode." ); case CORE: return lifecycleManagingDatabase( CORE_FACTORY ); case READ_REPLICA: