Java tutorial
/* * Copyright 2015-2017 Emmanuel Keller / QWAZR * <p> * 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 * <p> * http://www.apache.org/licenses/LICENSE-2.0 * <p> * 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 com.qwazr.library.cassandra; import com.datastax.driver.core.Cluster; import com.datastax.driver.core.Cluster.Builder; import com.datastax.driver.core.HostDistance; import com.datastax.driver.core.PoolingOptions; import com.datastax.driver.core.SocketOptions; import com.qwazr.utils.LoggerUtils; import com.qwazr.utils.concurrent.ReadWriteLock; import org.apache.commons.io.IOUtils; import java.io.Closeable; import java.io.IOException; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.logging.Logger; import java.util.stream.Collectors; public class CassandraCluster implements Closeable { private final static Logger logger = LoggerUtils.getLogger(CassandraCluster.class); private final ReadWriteLock rwl = ReadWriteLock.stamped(); private Cluster cluster; private final String login; private final String password; private final List<String> hosts; private CassandraSession rootSession; private final LinkedHashMap<String, CassandraSession> sessions; private final Integer connectTimeoutMs; private final Integer readTimeoutMs; private final Integer poolTimeoutMs; private final Integer poolConnections; public CassandraCluster(String login, String password, List<String> hosts, Integer connectTimeoutMs, Integer readTimeoutMs, Integer poolTimeoutMs, Integer poolConnections) { cluster = null; this.login = login; this.password = password == null ? login : password; this.connectTimeoutMs = connectTimeoutMs; this.readTimeoutMs = readTimeoutMs; this.poolTimeoutMs = poolTimeoutMs; this.poolConnections = poolConnections; this.hosts = hosts; sessions = new LinkedHashMap<>(); } @Override protected void finalize() throws Throwable { closeNoLock(); super.finalize(); } private void closeNoLock() { if (cluster != null) { IOUtils.closeQuietly(cluster); cluster = null; } } @Override public void close() throws IOException { rwl.write(() -> { rootSession = null; sessions.clear(); closeNoLock(); }); } private void checkCluster() { if (rwl.read(() -> cluster != null && !cluster.isClosed())) return; rwl.writeEx(() -> { if (cluster != null && !cluster.isClosed()) return; Builder builder = Cluster.builder(); if (hosts != null) for (String host : hosts) builder.addContactPoint(host); builder.withCredentials(login, password); SocketOptions socketOptions = builder.getConfiguration().getSocketOptions(); if (connectTimeoutMs != null) socketOptions.setConnectTimeoutMillis(connectTimeoutMs); if (readTimeoutMs != null) socketOptions.setReadTimeoutMillis(readTimeoutMs); PoolingOptions poolingOptions = builder.getConfiguration().getPoolingOptions(); if (poolTimeoutMs != null) poolingOptions.setPoolTimeoutMillis(poolTimeoutMs); if (poolConnections != null) { poolingOptions.setMaxConnectionsPerHost(HostDistance.LOCAL, poolConnections); poolingOptions.setCoreConnectionsPerHost(HostDistance.LOCAL, poolConnections); poolingOptions.setMaxConnectionsPerHost(HostDistance.REMOTE, poolConnections); poolingOptions.setCoreConnectionsPerHost(HostDistance.REMOTE, poolConnections); } cluster = builder.build(); logger.info("New Cluster " + hosts); rootSession = null; sessions.clear(); }); } public CassandraSession getSession() { checkCluster(); return rwl.readOrWrite(() -> rootSession, () -> rootSession = new CassandraSession(cluster)); } public CassandraSession getSession(final String keySpace) { if (keySpace == null) return getSession(); checkCluster(); final String fKeySpace = keySpace.intern(); return rwl.readOrWrite(() -> sessions.get(fKeySpace), () -> { CassandraSession session = new CassandraSession(cluster, keySpace); sessions.put(keySpace, session); return session; }); } public void expireUnusedSince(int minutes) { rwl.read(() -> { long time = System.currentTimeMillis() - (minutes * 60 * 1000); for (CassandraSession session : sessions.values()) if (session.getLastUse() < time) IOUtils.closeQuietly(session); }); rwl.write(() -> { List<String> keys = sessions.entrySet().stream().filter(entry -> entry.getValue().isClosed()) .map(Map.Entry::getKey).collect(Collectors.toList()); keys.forEach(key -> sessions.remove(key)); }); } public int getSessionCount() { return rwl.read(() -> sessions.size()); } }