org.neo4j.driver.internal.cluster.ClusterComposition Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of neo4j-java-driver Show documentation
Show all versions of neo4j-java-driver Show documentation
Access to the Neo4j graph database through Java
/*
* Copyright (c) 2002-2016 "Neo Technology,"
* Network Engine for Objects in Lund AB [http://neotechnology.com]
*
* This file is part of Neo4j.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.neo4j.driver.internal.cluster;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.neo4j.driver.internal.NetworkSession;
import org.neo4j.driver.internal.net.BoltServerAddress;
import org.neo4j.driver.internal.spi.Connection;
import org.neo4j.driver.internal.util.Clock;
import org.neo4j.driver.v1.Logger;
import org.neo4j.driver.v1.Record;
import org.neo4j.driver.v1.Statement;
import org.neo4j.driver.v1.StatementResult;
import org.neo4j.driver.v1.Value;
import org.neo4j.driver.v1.exceptions.ServiceUnavailableException;
import org.neo4j.driver.v1.exceptions.value.ValueException;
import org.neo4j.driver.v1.util.Function;
final class ClusterComposition
{
interface Provider
{
String GET_SERVERS = "CALL dbms.cluster.routing.getServers";
ClusterComposition getClusterComposition( Connection connection ) throws ServiceUnavailableException;
final class Default implements Provider
{
private static final Statement GET_SERVER = new Statement( Provider.GET_SERVERS );
private final Clock clock;
private final Logger log;
Default( Clock clock, Logger log )
{
this.clock = clock;
this.log = log;
}
@Override
public ClusterComposition getClusterComposition( Connection connection ) throws ServiceUnavailableException
{
StatementResult cursor = getServers( connection );
List records = cursor.list();
log.info( "Got getServers response: %s", records );
long now = clock.millis();
try
{
if ( records.size() != 1 )
{
// server returned too few or too many rows, this is a contract violation, treat as incapable
return null;
}
return read( records.get( 0 ), now );
}
finally
{
cursor.consume(); // make sure we exhaust the results
}
}
private StatementResult getServers( Connection connection )
{
return NetworkSession.run( connection, GET_SERVER );
}
}
}
private static final long MAX_TTL = Long.MAX_VALUE / 1000L;
private static final Function OF_BoltServerAddress =
new Function()
{
@Override
public BoltServerAddress apply( Value value )
{
return new BoltServerAddress( value.asString() );
}
};
private final Set readers, writers, routers;
final long expirationTimestamp;
private ClusterComposition( long expirationTimestamp )
{
this.readers = new HashSet<>();
this.writers = new HashSet<>();
this.routers = new HashSet<>();
this.expirationTimestamp = expirationTimestamp;
}
/** For testing */
ClusterComposition(
long expirationTimestamp,
Set readers,
Set writers,
Set routers )
{
this( expirationTimestamp );
this.readers.addAll( readers );
this.writers.addAll( writers );
this.routers.addAll( routers );
}
public boolean isValid()
{
return !routers.isEmpty() && !writers.isEmpty();
}
public Set readers()
{
return new HashSet<>( readers );
}
public Set writers()
{
return new HashSet<>( writers );
}
public Set routers()
{
return new HashSet<>( routers );
}
@Override
public String toString()
{
return "ClusterComposition{" +
"expirationTimestamp=" + expirationTimestamp +
", readers=" + readers +
", writers=" + writers +
", routers=" + routers +
'}';
}
private static ClusterComposition read( Record record, long now )
{
if ( record == null )
{
return null;
}
try
{
final ClusterComposition result;
result = new ClusterComposition( expirationTimestamp( now, record ) );
record.get( "servers" ).asList( new Function()
{
@Override
public Void apply( Value value )
{
result.servers( value.get( "role" ).asString() )
.addAll( value.get( "addresses" ).asList( OF_BoltServerAddress ) );
return null;
}
} );
return result;
}
catch ( ValueException e )
{
return null;
}
}
private static long expirationTimestamp( long now, Record record )
{
long ttl = record.get( "ttl" ).asLong();
long expirationTimestamp = now + ttl * 1000;
if ( ttl < 0 || ttl >= MAX_TTL || expirationTimestamp < 0 )
{
expirationTimestamp = Long.MAX_VALUE;
}
return expirationTimestamp;
}
private Set servers( String role )
{
switch ( role )
{
case "READ":
return readers;
case "WRITE":
return writers;
case "ROUTE":
return routers;
default:
throw new IllegalArgumentException( "invalid server role: " + role );
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy