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

com.netflix.astyanax.cql.CqlClusterImpl Maven / Gradle / Ivy

package com.netflix.astyanax.cql;

import static com.datastax.driver.core.querybuilder.QueryBuilder.eq;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Properties;

import com.codahale.metrics.MetricRegistryListener;
import com.datastax.driver.core.Cluster;
import com.datastax.driver.core.Configuration;
import com.datastax.driver.core.Row;
import com.datastax.driver.core.Session;
import com.datastax.driver.core.Statement;
import com.datastax.driver.core.querybuilder.QueryBuilder;
import com.google.common.base.Function;
import com.google.common.collect.Lists;
import com.netflix.astyanax.AstyanaxConfiguration;
import com.netflix.astyanax.Keyspace;
import com.netflix.astyanax.KeyspaceTracerFactory;
import com.netflix.astyanax.connectionpool.ConnectionPoolConfiguration;
import com.netflix.astyanax.connectionpool.ConnectionPoolMonitor;
import com.netflix.astyanax.connectionpool.ConnectionPoolProxy.SeedHostListener;
import com.netflix.astyanax.connectionpool.Host;
import com.netflix.astyanax.connectionpool.OperationResult;
import com.netflix.astyanax.connectionpool.exceptions.ConnectionException;
import com.netflix.astyanax.cql.schema.CqlColumnDefinitionImpl;
import com.netflix.astyanax.cql.schema.CqlColumnFamilyDefinitionImpl;
import com.netflix.astyanax.cql.schema.CqlKeyspaceDefinitionImpl;
import com.netflix.astyanax.ddl.ColumnDefinition;
import com.netflix.astyanax.ddl.ColumnFamilyDefinition;
import com.netflix.astyanax.ddl.KeyspaceDefinition;
import com.netflix.astyanax.ddl.SchemaChangeResult;

/**
 * Java Driver based impl of {@link Cluster} that implements ddl operations.
 * The class encapsulates a java driver cluster and session object to provide all the functionality. 
 *  
 * Note that due to the way the object is setup via AstyanaxContext and CqlFamilyFactory, it needs to implements 
 * a {@link SeedHostListener} so that it can construct the cluster and session object appropriately once the seed hosts
 * have been provided by the {@link HostSupplier} object
 *  
 * @author poberai
 */
public class CqlClusterImpl implements com.netflix.astyanax.Cluster, SeedHostListener {

	public volatile Cluster cluster;
	private volatile Session session;
	private final AstyanaxConfiguration astyanaxConfig; 
	private final KeyspaceTracerFactory tracerFactory; 
	private final Configuration javaDriverConfig; 
	private final ConnectionPoolMonitor cpMonitor;
	private final MetricRegistryListener metricsRegListener;
	
	public CqlClusterImpl(AstyanaxConfiguration asConfig, KeyspaceTracerFactory tracerFactory, ConnectionPoolConfiguration cpConfig, ConnectionPoolMonitor cpMonitor) {
		this.astyanaxConfig = asConfig;
		this.tracerFactory = tracerFactory;
		this.javaDriverConfig = ((JavaDriverConnectionPoolConfigurationImpl)cpConfig).getJavaDriverConfig();
		this.cpMonitor = cpMonitor;
		this.metricsRegListener = ((JavaDriverConnectionPoolMonitorImpl)cpMonitor).getMetricsRegistryListener();
	}

	@Override
	public String describeClusterName() throws ConnectionException {
		return cluster.getMetadata().getClusterName();
	}

	@Override
	public String getVersion() throws ConnectionException {
		
		Statement query = QueryBuilder.select("release_version")
								  .from("system", "local")
								  .where(eq("key", "local"));
		
		return session.execute(query).one().getString("release_version"); 
	}

	public void shutdown() {
		cluster.close();
	}
	
	@Override
	public String describeSnitch() throws ConnectionException {
		throw new UnsupportedOperationException("Operation not supported");
	}

	@Override
	public String describePartitioner() throws ConnectionException {
		Statement query = QueryBuilder.select("partitioner")
				.from("system", "local")
				.where(eq("key", "local"));

		return session.execute(query).one().getString("partitioner"); 
	}

	@Override
	public Map> describeSchemaVersions() throws ConnectionException {
		return new CqlSchemaVersionReader(session).exec();
	}

	@Override
	public KeyspaceDefinition makeKeyspaceDefinition() {
        return new CqlKeyspaceDefinitionImpl(session);
	}

	@Override
	public Properties getAllKeyspaceProperties() throws ConnectionException {

		Properties properties = new Properties();
		try {
			List ksDefs = describeKeyspaces();
			for(KeyspaceDefinition ksDef : ksDefs) {
				Properties ksProps = ksDef.getProperties();
				for (Object key : ksProps.keySet()) {
					properties.put(ksDef.getName() + "." + key, ksProps.get(key));
				}
			}
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
		return properties;
	}

	@Override
	public Properties getKeyspaceProperties(String keyspace) throws ConnectionException {
		
		try {
			return describeKeyspace(keyspace.toLowerCase()).getProperties();
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}

	@Override
	public List describeKeyspaces() throws ConnectionException {
		
		Statement query = QueryBuilder.select().all().from("system", "schema_keyspaces");

		List ksDefs = new ArrayList();
		try {
			for(Row row : session.execute(query).all()) {
				String keyspaceName = row.getString("keyspace_name");
				if (keyspaceName.equals("system") || keyspaceName.startsWith("system_")) {
					continue;
				}
				ksDefs.add(new CqlKeyspaceDefinitionImpl(session, row));
			}
			return ksDefs;
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}

	@Override
	public KeyspaceDefinition describeKeyspace(String ksName) throws ConnectionException {
		return new CqlKeyspaceImpl(session, ksName, astyanaxConfig, tracerFactory,cpMonitor).describeKeyspace();
	}

	@Override
	public Keyspace getKeyspace(String keyspace) throws ConnectionException {
		return new CqlKeyspaceImpl(session, keyspace, astyanaxConfig, tracerFactory,cpMonitor);
	}

	@Override
	public OperationResult dropKeyspace(String keyspaceName) throws ConnectionException {
		return new CqlKeyspaceImpl(session, keyspaceName.toLowerCase(), astyanaxConfig, tracerFactory,cpMonitor).dropKeyspace();
	}

	@Override
	public OperationResult addKeyspace(KeyspaceDefinition def) throws ConnectionException {
		return ((CqlKeyspaceDefinitionImpl)def).execute();
	}

	@Override
	public OperationResult updateKeyspace(KeyspaceDefinition def) throws ConnectionException {
		return ((CqlKeyspaceDefinitionImpl)def).alterKeyspace().execute();
	}

	@Override
	public OperationResult createKeyspace(Map options) throws ConnectionException {
		String keyspaceName = (String) options.remove("name");
		if (keyspaceName == null) {
			throw new RuntimeException("Options missing 'name' property for keyspace name");
		}
		return new CqlKeyspaceDefinitionImpl(session, options).setName(keyspaceName).execute();
	}

	@Override
	public OperationResult createKeyspace(Properties props) throws ConnectionException {
		String keyspaceName = (String) props.remove("name");
		if (keyspaceName == null) {
			throw new RuntimeException("Options missing 'name' property for keyspace name");
		}
		return new CqlKeyspaceDefinitionImpl(session, props).setName(keyspaceName).execute();
	}

	@Override
	public OperationResult updateKeyspace(Map options) throws ConnectionException {
		String keyspaceName = (String) options.remove("name");
		if (keyspaceName == null) {
			throw new RuntimeException("Options missing 'name' property for keyspace name");
		}
		return new CqlKeyspaceDefinitionImpl(session, options).setName(keyspaceName).alterKeyspace().execute();
	}

	@Override
	public OperationResult updateKeyspace(Properties props) throws ConnectionException {
		String keyspaceName = (String) props.remove("name");
		if (keyspaceName == null) {
			throw new RuntimeException("Options missing 'name' property for keyspace name");
		}
		return new CqlKeyspaceDefinitionImpl(session, props).setName(keyspaceName).alterKeyspace().execute();
	}
	
	@Override
	public AstyanaxConfiguration getConfig() {
		return astyanaxConfig;
	}

	@Override
	public ColumnFamilyDefinition makeColumnFamilyDefinition() {
		return new CqlColumnFamilyDefinitionImpl(session);
	}

	@Override
	public ColumnDefinition makeColumnDefinition() {
		return new CqlColumnDefinitionImpl();
	}
	
	@Override
	public Properties getColumnFamilyProperties(String keyspace, String columnfamilyName) throws ConnectionException {
		try {
			return new CqlKeyspaceDefinitionImpl(session).setName(keyspace).getColumnFamily(columnfamilyName).getProperties();
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}

	@Override
	public OperationResult createColumnFamily(Map options) throws ConnectionException {
		return new CqlColumnFamilyDefinitionImpl(session, null, options).execute();
	}

	@Override
	public OperationResult createColumnFamily(Properties props) throws ConnectionException {
		return new CqlColumnFamilyDefinitionImpl(session, null, props).execute();
	}

	@Override
	public OperationResult updateColumnFamily(Map options) throws ConnectionException {
		return new CqlColumnFamilyDefinitionImpl(session, null, options).alterTable().execute();
	}

	@Override
	public OperationResult updateColumnFamily(Properties props) throws ConnectionException {
		return new CqlColumnFamilyDefinitionImpl(session, null, props).alterTable().execute();
	}

	@Override
	public OperationResult dropColumnFamily(String keyspaceName, String columnFamilyName) throws ConnectionException {
		return new CqlKeyspaceImpl(session, keyspaceName, astyanaxConfig, tracerFactory,cpMonitor).dropColumnFamily(columnFamilyName);
	}

	@Override
	public OperationResult addColumnFamily(ColumnFamilyDefinition def) throws ConnectionException {
		return ((CqlColumnFamilyDefinitionImpl)def).execute();
	}

	@Override
	public OperationResult updateColumnFamily(ColumnFamilyDefinition def) throws ConnectionException {
		return ((CqlColumnFamilyDefinitionImpl)def).alterTable().execute();
	}

	@Override
	public void setHosts(Collection hosts, int port) {
		
		List hostList = Lists.newArrayList(hosts);
		
		List contactPoints = Lists.transform(hostList, new Function() {
			@Override
			public String apply(Host input) {
				if (input != null) {
					return input.getHostName(); 
				}
				return null;
			}
		});
		
		Configuration config = javaDriverConfig;
		
		// We really need a mechanism to easily override Configuration on the builder
		Cluster.Builder builder = Cluster.builder()
				.addContactPoints(contactPoints.toArray(new String[0]))
				.withPort(port)
				.withLoadBalancingPolicy(config.getPolicies().getLoadBalancingPolicy())
				.withReconnectionPolicy(config.getPolicies().getReconnectionPolicy())
				.withRetryPolicy(config.getPolicies().getRetryPolicy())
				.withCompression(config.getProtocolOptions().getCompression())
				.withPoolingOptions(config.getPoolingOptions())
				.withSocketOptions(config.getSocketOptions())
				.withQueryOptions(config.getQueryOptions());
		
		if (config.getMetricsOptions() == null) {
			builder.withoutMetrics();
		} else if (!config.getMetricsOptions().isJMXReportingEnabled()) {
			builder.withoutJMXReporting();
		}
				
		this.cluster = builder.build(); 
		if (!(this.cpMonitor instanceof JavaDriverConnectionPoolMonitorImpl))
			this.cluster.getMetrics().getRegistry().addListener((MetricRegistryListener) this.metricsRegListener);
		this.session = cluster.connect();
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy