package net.iponweb.disthene.reader.service.store; import com.datastax.driver.core.*; import com.datastax.driver.core.policies.DowngradingConsistencyRetryPolicy; import net.iponweb.disthene.reader.config.StoreConfiguration; import net.iponweb.disthene.reader.utils.CassandraLoadBalancingPolicies; import org.apache.log4j.Logger; import java.util.Collection; /** * @author Andrei Ivanov */ public class CassandraService { private Logger logger = Logger.getLogger(CassandraService.class); private Cluster cluster; private Session session; private final PreparedStatement statement; public CassandraService(StoreConfiguration storeConfiguration) { String query = "SELECT time, data FROM " + storeConfiguration.getKeyspace() + "." + storeConfiguration.getColumnFamily() + " where path = ? and tenant = ? and period = ? and rollup = ? and time >= ? and time <= ? order by time"; SocketOptions socketOptions = new SocketOptions() .setReceiveBufferSize(1024 * 1024) .setSendBufferSize(1024 * 1024) .setTcpNoDelay(false) .setReadTimeoutMillis((int) (storeConfiguration.getReadTimeout() * 1000)) .setConnectTimeoutMillis((int) (storeConfiguration.getConnectTimeout() * 1000)); PoolingOptions poolingOptions = new PoolingOptions(); poolingOptions.setMaxConnectionsPerHost(HostDistance.LOCAL, storeConfiguration.getMaxConnections()); poolingOptions.setMaxConnectionsPerHost(HostDistance.REMOTE, storeConfiguration.getMaxConnections()); poolingOptions.setMaxRequestsPerConnection(HostDistance.REMOTE, storeConfiguration.getMaxRequests()); poolingOptions.setMaxRequestsPerConnection(HostDistance.LOCAL, storeConfiguration.getMaxRequests()); Cluster.Builder builder = Cluster.builder() .withSocketOptions(socketOptions) .withCompression(ProtocolOptions.Compression.LZ4) .withLoadBalancingPolicy(CassandraLoadBalancingPolicies.getLoadBalancingPolicy(storeConfiguration.getLoadBalancingPolicyName())) .withRetryPolicy(DowngradingConsistencyRetryPolicy.INSTANCE) .withPoolingOptions(poolingOptions) .withQueryOptions(new QueryOptions().setConsistencyLevel(ConsistencyLevel.valueOf(storeConfiguration.getConsistency()))) .withProtocolVersion(ProtocolVersion.valueOf(storeConfiguration.getProtocolVersion())) .withPort(storeConfiguration.getPort()); if ( storeConfiguration.getUserName() != null && storeConfiguration.getUserPassword() != null) { builder = builder.withCredentials(storeConfiguration.getUserName(), storeConfiguration.getUserPassword()); } for (String cp : storeConfiguration.getCluster()) { builder.addContactPoint(cp); } cluster = builder.build(); Metadata metadata = cluster.getMetadata(); logger.debug("Connected to cluster: " + metadata.getClusterName()); for (Host host : metadata.getAllHosts()) { logger.debug(String.format("Datacenter: %s; Host: %s; Rack: %s", host.getDatacenter(), host.getAddress(), host.getRack())); } session = cluster.connect(); statement = session.prepare(query); } public ResultSetFuture executeAsync(String tenant, String path, int period, int rollup, long from, long to) { return session.executeAsync(statement.bind(path, tenant, period, rollup, from, to)); } public void shutdown() { logger.info("Closing C* session"); logger.info("Waiting for C* queries to be completed"); while (getInFlightQueries(session.getState()) > 0) { try { Thread.sleep(100); } catch (InterruptedException ignored) { } } session.close(); logger.info("Closing C* cluster"); cluster.close(); } private int getInFlightQueries(Session.State state) { int result = 0; Collection<Host> hosts = state.getConnectedHosts(); for(Host host : hosts) { result += state.getInFlightQueries(host); } return result; } }