All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.datastax.driver.dse.DseCluster Maven / Gradle / Ivy

Go to download

A driver for DataStax Enterprise (DSE) and Apache Cassandra 1.2+ clusters that works exclusively with the Cassandra Query Language version 3 (CQL3) and Cassandra's binary protocol, supporting DSE-specific features such as geospatial types, DSE Graph and DSE authentication.

There is a newer version: 2.4.0
Show newest version
/*
 * Copyright DataStax, Inc.
 *
 * This software can be used solely with DataStax Enterprise. Please consult the license at
 * http://www.datastax.com/terms/datastax-dse-driver-license-terms
 */
package com.datastax.driver.dse;

import static com.google.common.base.Preconditions.checkArgument;

import com.datastax.driver.core.AuthProvider;
import com.datastax.driver.core.Cluster;
import com.datastax.driver.core.CodecRegistry;
import com.datastax.driver.core.DelegatingCluster;
import com.datastax.driver.core.Host;
import com.datastax.driver.core.NettyOptions;
import com.datastax.driver.core.PoolingOptions;
import com.datastax.driver.core.ProtocolOptions;
import com.datastax.driver.core.ProtocolVersion;
import com.datastax.driver.core.QueryOptions;
import com.datastax.driver.core.SSLOptions;
import com.datastax.driver.core.Session;
import com.datastax.driver.core.SocketOptions;
import com.datastax.driver.core.ThreadingOptions;
import com.datastax.driver.core.TimestampGenerator;
import com.datastax.driver.core.TypeCodec;
import com.datastax.driver.core.exceptions.AuthenticationException;
import com.datastax.driver.core.exceptions.CodecNotFoundException;
import com.datastax.driver.core.exceptions.InvalidQueryException;
import com.datastax.driver.core.exceptions.NoHostAvailableException;
import com.datastax.driver.core.policies.AddressTranslator;
import com.datastax.driver.core.policies.LoadBalancingPolicy;
import com.datastax.driver.core.policies.Policies;
import com.datastax.driver.core.policies.ReconnectionPolicy;
import com.datastax.driver.core.policies.RetryPolicy;
import com.datastax.driver.core.policies.SpeculativeExecutionPolicy;
import com.datastax.driver.dse.auth.DsePlainTextAuthProvider;
import com.datastax.driver.dse.geometry.codecs.LineStringCodec;
import com.datastax.driver.dse.geometry.codecs.PointCodec;
import com.datastax.driver.dse.geometry.codecs.PolygonCodec;
import com.datastax.driver.dse.graph.GraphOptions;
import com.datastax.driver.dse.graph.GraphStatement;
import com.datastax.driver.dse.search.DateRangeCodec;
import com.google.common.base.Function;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.util.Collection;
import java.util.UUID;
import java.util.concurrent.Future;

/**
 * Information and known state of a DSE cluster.
 *
 * 

This is the main entry point of the DSE driver. It extends the CQL driver's {@link Cluster} * object with DSE-specific features. A simple example of access to a DSE cluster would be: * *

 *   DseCluster cluster = DseCluster.builder().addContactPoint("192.168.0.1").build();
 *   DseSession session = cluster.connect("db1");
 *
 *   for (Row row : session.execute("SELECT * FROM table1"))
 *       // do something ...
 * 
*/ public class DseCluster extends DelegatingCluster { /** * Returns the current version of the DSE driver. * *

This is intended for products that wrap or extend the driver, as a way to check * compatibility if end-users override the driver version in their application. * *

This method is an alias for {@link Cluster#getDriverVersion()}; both return exactly the same * version. * * @return the DSE driver version. */ public static String getDseDriverVersion() { return Cluster.getDriverVersion(); } private final Cluster delegate; /** Helper class to build {@link DseCluster} instances. */ public static class Builder extends Cluster.Builder { private GraphOptions graphOptions; private boolean geospatialCodecs = true; private boolean searchCodecs = true; private String applicationName = null; private String applicationVersion = null; private UUID id = null; public Builder() { this.withLoadBalancingPolicy(DseConfiguration.defaultLoadBalancingPolicy()); } /** * Sets the default options to use with graph queries. * *

If you don't provide this, the new cluster will get a {@link GraphOptions} instance with * the default values. * * @param graphOptions the graph options. * @return this builder (for method chaining). */ public DseCluster.Builder withGraphOptions(GraphOptions graphOptions) { this.graphOptions = graphOptions; return this; } /** * Prevents the registration of {@link com.datastax.driver.dse.geometry.codecs geospatial * codecs} with the new cluster. * *

If this method is not called, those codecs will be registered by default. * * @return this builder (for method chaining). * @see CodecRegistry * @see TypeCodec */ public DseCluster.Builder withoutGeospatialCodecs() { this.geospatialCodecs = false; return this; } /** * Prevents the registration of search codecs with the new cluster. * *

Currently only {@link DateRangeCodec} is affected by this method. If this method is not * called, this codec will be registered by default. * * @return this builder (for method chaining). * @see CodecRegistry * @see TypeCodec */ public DseCluster.Builder withoutSearchCodecs() { this.searchCodecs = false; return this; } @Override public DseCluster.Builder withClusterName(String name) { return (DseCluster.Builder) super.withClusterName(name); } /** * An optional configuration for providing a unique identifier for the created client instance. * *

If not provided, an id will generated. * *

This value is passed to DSE and is useful as metadata for describing a client connection. * * @param id the id to assign to this client instance. * @return this Builder. * @deprecated Use {@link #withClientId(UUID)}} instead. This method was intended to give a * client id not cluster id from the beginning. The withClientId name is more appropriate. */ @Deprecated public DseCluster.Builder withClusterId(UUID id) { withClientId(id); return this; } /** * An optional configuration for providing a unique identifier for the created client instance. * *

If not provided, an id will generated. * *

This value is passed to DSE and is useful as metadata for describing a client connection. * * @param id the id to assign to this client instance. * @return this Builder. */ public DseCluster.Builder withClientId(UUID id) { this.id = id; return this; } /** * An optional configuration identifying the name of the application using this cluster. * *

This value is passed to DSE and is useful as metadata for describing a client connection. * * @param name the name of the application using this cluster. * @return this Builder. */ public DseCluster.Builder withApplicationName(String name) { this.applicationName = name; return this; } /** * An optional configuration identifying the version of the application using this cluster. * *

This value is to passed to DSE and is useful as metadata for describing a client * connection. * * @param version the version of the application using this cluster. * @return this Builder. */ public DseCluster.Builder withApplicationVersion(String version) { this.applicationVersion = version; return this; } @Override public DseCluster.Builder withPort(int port) { return (DseCluster.Builder) super.withPort(port); } @Override public DseCluster.Builder allowBetaProtocolVersion() { return (DseCluster.Builder) super.allowBetaProtocolVersion(); } @Override public DseCluster.Builder withMaxSchemaAgreementWaitSeconds(int maxSchemaAgreementWaitSeconds) { return (DseCluster.Builder) super.withMaxSchemaAgreementWaitSeconds(maxSchemaAgreementWaitSeconds); } @Override public DseCluster.Builder withProtocolVersion(ProtocolVersion version) { return (DseCluster.Builder) super.withProtocolVersion(version); } @Override public Builder withMonitorReporting(boolean enabled) { return (DseCluster.Builder) super.withMonitorReporting(enabled); } @Override public DseCluster.Builder addContactPoint(String address) { return (Builder) super.addContactPoint(address); } @Override public DseCluster.Builder addContactPoints(String... addresses) { return (Builder) super.addContactPoints(addresses); } @Override public DseCluster.Builder addContactPoints(InetAddress... addresses) { return (Builder) super.addContactPoints(addresses); } @Override public DseCluster.Builder addContactPoints(Collection addresses) { return (Builder) super.addContactPoints(addresses); } @Override public DseCluster.Builder addContactPointsWithPorts(InetSocketAddress... addresses) { return (DseCluster.Builder) super.addContactPointsWithPorts(addresses); } @Override public DseCluster.Builder addContactPointsWithPorts(Collection addresses) { return (Builder) super.addContactPointsWithPorts(addresses); } /** * Configures the load balancing policy to use for the new DSE cluster. * *

If you use graph analytics queries, it should be wrapped into a {@link * DseLoadBalancingPolicy} to ensure that queries are routed optimally. * *

If no load balancing policy is set through this method, the default is to use a {@link * Policies#defaultLoadBalancingPolicy()} wrapped into a {@code TargetingLoadBalancingPolicy}. * * @param policy the load balancing policy to use. * @return this builder. */ @Override public DseCluster.Builder withLoadBalancingPolicy(LoadBalancingPolicy policy) { return (DseCluster.Builder) super.withLoadBalancingPolicy(policy); } @Override public DseCluster.Builder withReconnectionPolicy(ReconnectionPolicy policy) { return (DseCluster.Builder) super.withReconnectionPolicy(policy); } @Override public DseCluster.Builder withRetryPolicy(RetryPolicy policy) { return (DseCluster.Builder) super.withRetryPolicy(policy); } @Override public DseCluster.Builder withAddressTranslator(AddressTranslator translator) { return (DseCluster.Builder) super.withAddressTranslator(translator); } @Override public DseCluster.Builder withTimestampGenerator(TimestampGenerator timestampGenerator) { return (DseCluster.Builder) super.withTimestampGenerator(timestampGenerator); } @Override public DseCluster.Builder withSpeculativeExecutionPolicy(SpeculativeExecutionPolicy policy) { return (DseCluster.Builder) super.withSpeculativeExecutionPolicy(policy); } @Override public DseCluster.Builder withCodecRegistry(CodecRegistry codecRegistry) { return (DseCluster.Builder) super.withCodecRegistry(codecRegistry); } @Override public DseCluster.Builder withCredentials(String username, String password) { return withAuthProvider(new DsePlainTextAuthProvider(username, password)); } @Override public DseCluster.Builder withAuthProvider(AuthProvider authProvider) { return (DseCluster.Builder) super.withAuthProvider(authProvider); } @Override public DseCluster.Builder withCompression(ProtocolOptions.Compression compression) { return (DseCluster.Builder) super.withCompression(compression); } @Override public DseCluster.Builder withoutMetrics() { return (DseCluster.Builder) super.withoutMetrics(); } @Override public DseCluster.Builder withSSL() { return (DseCluster.Builder) super.withSSL(); } @Override public DseCluster.Builder withSSL(SSLOptions sslOptions) { return (DseCluster.Builder) super.withSSL(sslOptions); } @Override public DseCluster.Builder withInitialListeners(Collection listeners) { return (DseCluster.Builder) super.withInitialListeners(listeners); } @Override public DseCluster.Builder withoutJMXReporting() { return (DseCluster.Builder) super.withoutJMXReporting(); } @Override public DseCluster.Builder withPoolingOptions(PoolingOptions options) { return (DseCluster.Builder) super.withPoolingOptions(options); } @Override public DseCluster.Builder withSocketOptions(SocketOptions options) { return (DseCluster.Builder) super.withSocketOptions(options); } @Override public DseCluster.Builder withQueryOptions(QueryOptions options) { return (DseCluster.Builder) super.withQueryOptions(options); } @Override public DseCluster.Builder withThreadingOptions(ThreadingOptions options) { return (DseCluster.Builder) super.withThreadingOptions(options); } @Override public DseCluster.Builder withNettyOptions(NettyOptions nettyOptions) { return (DseCluster.Builder) super.withNettyOptions(nettyOptions); } @Override public DseCluster.Builder withNoCompact() { return (DseCluster.Builder) super.withNoCompact(); } @Override public DseCluster build() { DseCluster dseCluster = new DseCluster(super.build()); CodecRegistry codecRegistry = dseCluster.getConfiguration().getCodecRegistry(); if (geospatialCodecs) { registerGeospatialCodecs(codecRegistry); } if (searchCodecs) { registerSearchCodecs(codecRegistry); } return dseCluster; } @Override public DseConfiguration getConfiguration() { return new DseConfiguration( super.getConfiguration(), graphOptions != null ? graphOptions : new GraphOptions(), applicationName, applicationVersion, id); } private static void registerGeospatialCodecs(CodecRegistry codecRegistry) { registerCodecIfNotPresent(codecRegistry, LineStringCodec.INSTANCE); registerCodecIfNotPresent(codecRegistry, PointCodec.INSTANCE); registerCodecIfNotPresent(codecRegistry, PolygonCodec.INSTANCE); } private static void registerSearchCodecs(CodecRegistry codecRegistry) { registerCodecIfNotPresent(codecRegistry, DateRangeCodec.INSTANCE); } private static void registerCodecIfNotPresent(CodecRegistry codecRegistry, TypeCodec codec) { try { codecRegistry.codecFor(codec.getCqlType(), codec.getJavaType()); } catch (CodecNotFoundException e) { codecRegistry.register(codec); } } } /** * Creates a new {@link DseCluster.Builder} instance. * *

This is a convenience method for {@code new GraphCluster.Builder()}. * * @return the new cluster builder. */ public static DseCluster.Builder builder() { return new DseCluster.Builder(); } private DseCluster(Cluster delegate) { checkArgument( delegate.getConfiguration() instanceof DseConfiguration, "Cannot create a GraphCluster without a GraphConfiguration"); this.delegate = delegate; } @Override public DseConfiguration getConfiguration() { return (DseConfiguration) super.getConfiguration(); } @Override protected Cluster delegate() { return delegate; } /** * Creates a new DSE session on this cluster but does not initialize it. * *

Because this method does not perform any initialization, it cannot fail. The initialization * of the session (the connection of the session to the Cassandra nodes) will occur if either the * {@link DseSession#init} method is called explicitly, or whenever the returned object is used. * *

Once a session returned by this method gets initialized (see above), it will be set to no * keyspace. If you want to set such session to a keyspace, you will have to explicitly execute a * 'USE mykeyspace' query. * *

Note that if you do not particularly need to defer initialization, it is simpler to use one * of the {@code connect()} methods of this class. * * @return a new, non-initialized DSE session on this cluster. */ @Override public DseSession newSession() { return new DefaultDseSession(super.newSession(), this); } /** * Creates a new DSE session on this cluster and initializes it. * *

This method will initialize the newly created session, trying to connect to the Cassandra * nodes before returning. If you only want to create a session without initializing it right * away, see {@link #newSession}. * * @return a new session on this cluster set to no keyspace. * @throws NoHostAvailableException if the Cluster has not been initialized yet ({@link #init} has * not be called and this is the first connect call) and no host amongst the contact points * can be reached. * @throws AuthenticationException if an authentication error occurs while contacting the initial * contact points. * @throws IllegalStateException if the Cluster was closed prior to calling this method. This can * occur either directly (through {@link #close()} or {@link #closeAsync()}), or as a result * of an error while initializing the Cluster. */ @Override public DseSession connect() { return new DefaultDseSession(super.connect(), this); } /** * Creates a new DSE session on this cluster, initializes it and sets the keyspace to the provided * one. * *

This method will initialize the newly created session, trying to connect to the Cassandra * nodes before returning. If you only want to create a session without initializing it right * away, see {@link #newSession}. * *

The keyspace set through this method is only valid for CQL queries; for graph queries, the * graph to target is determined by the graph name specified via {@link * GraphStatement#setGraphName(String)}} or {@link GraphOptions#setGraphName(String)}. * * @param keyspace the name of the keyspace to use for the created {@link DseSession}. * @return a new session on this cluster set to keyspace {@code keyspace}. * @throws NoHostAvailableException if the Cluster has not been initialized yet ({@link #init} has * not be called and this is the first connect call) and no host amongst the contact points * can be reached, or if no host can be contacted to set the {@code keyspace}. * @throws AuthenticationException if an authentication error occurs while contacting the initial * contact points. * @throws InvalidQueryException if the keyspace does not exist. * @throws IllegalStateException if the Cluster was closed prior to calling this method. This can * occur either directly (through {@link #close()} or {@link #closeAsync()}), or as a result * of an error while initializing the Cluster. */ @Override public DseSession connect(String keyspace) { return new DefaultDseSession(super.connect(keyspace), this); } /** * Creates a new DSE session on this cluster and initializes it asynchronously. * *

This will also initialize the {@code Cluster} if needed; note that cluster initialization * happens synchronously on the thread that called this method. Therefore it is recommended to * initialize the cluster at application startup, and not rely on this method to do it. * *

The {@link Session} object returned by the future's {@link Future#get() get} method can be * safely cast to {@link DseSession}. * * @return a future that will complete when the session is fully initialized. * @throws NoHostAvailableException if the Cluster has not been initialized yet ({@link #init} has * not been called and this is the first connect call) and no host amongst the contact points * can be reached. * @throws IllegalStateException if the Cluster was closed prior to calling this method. This can * occur either directly (through {@link #close()} or {@link #closeAsync()}), or as a result * of an error while initializing the Cluster. * @see #connect() */ @Override public ListenableFuture connectAsync() { return Futures.transform( super.connectAsync(), new Function() { @Override public Session apply(Session input) { return new DefaultDseSession(input, DseCluster.this); } }); } /** * Creates a new DSE session on this cluster, and initializes it to the given keyspace * asynchronously. * *

This will also initialize the {@code Cluster} if needed; note that cluster initialization * happens synchronously on the thread that called this method. Therefore it is recommended to * initialize the cluster at application startup, and not rely on this method to do it. * *

The keyspace set through this method is only valid for CQL queries; for graph queries, the * graph to target is determined by the graph name specified via {@link * GraphStatement#setGraphName(String)}} or {@link GraphOptions#setGraphName(String)}. * *

The {@link Session} object returned by the future's {@link Future#get() get} method can be * safely cast to {@link DseSession}. * * @param keyspace The name of the keyspace to use for the created {@code Session}. * @return a future that will complete when the session is fully initialized. * @throws NoHostAvailableException if the Cluster has not been initialized yet ({@link #init} has * not been called and this is the first connect call) and no host amongst the contact points * can be reached. * @throws IllegalStateException if the Cluster was closed prior to calling this method. This can * occur either directly (through {@link #close()} or {@link #closeAsync()}), or as a result * of an error while initializing the Cluster. */ @Override public ListenableFuture connectAsync(String keyspace) { return Futures.transform( super.connectAsync(keyspace), new Function() { @Override public Session apply(Session input) { return new DefaultDseSession(input, DseCluster.this); } }); } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy