/************************************************************************* * (c) Copyright 2016 Hewlett Packard Enterprise Development Company LP * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 3 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see http://www.gnu.org/licenses/. ************************************************************************/ package com.eucalyptus.simplequeue.persistence.cassandra; import com.datastax.driver.core.Cluster; import com.datastax.driver.core.Session; import com.eucalyptus.cassandra.common.CassandraComponent; import com.eucalyptus.cassandra.common.CassandraKeyspaceSpecification; import com.eucalyptus.cassandra.common.CassandraPersistence; import com.eucalyptus.cassandra.common.util.CqlUtil; import com.eucalyptus.configurable.ConfigurableProperty; import com.eucalyptus.configurable.ConfigurablePropertyException; import com.eucalyptus.configurable.PropertyChangeListener; import com.eucalyptus.simplequeue.config.SimpleQueueProperties; import com.eucalyptus.simplequeue.exceptions.SimpleQueueException; import com.eucalyptus.util.Exceptions; import com.eucalyptus.util.ThrowingFunction; import com.google.common.base.Splitter; import com.google.common.collect.Lists; import com.google.common.io.Resources; import org.apache.log4j.Logger; import java.io.IOException; import java.nio.charset.StandardCharsets; import java.text.ParseException; import java.util.List; import java.util.function.Function; /** * Created by ethomas on 11/22/16. */ @CassandraKeyspaceSpecification( "eucalyptus_simplequeue" ) public class CassandraSessionManager implements CassandraComponent { private static final Logger LOG = Logger.getLogger(CassandraSessionManager.class); private static final CassandraSessionManager external = new CassandraSessionManager(); private Cluster cluster = null; private Session session = null; public static CassandraSessionManager external( ) { return external; } private synchronized void initCluster() { initCluster(SimpleQueueProperties.CASSANDRA_HOST); } private synchronized void initCluster(String contactPoint) { if (session != null) { session.close(); session = null; } if (cluster != null) { cluster.close(); cluster = null; } LOG.info("Trying to connect to the cluster " + contactPoint); List<String> contactPoints = Lists.newArrayList(); for (String s: Splitter.on(",").omitEmptyStrings().split(contactPoint)) { contactPoints.add(s); } cluster = Cluster.builder().addContactPoints(contactPoints.toArray(new String[0])).build(); session = cluster.connect(); createSchema( session ); } private static void createSchema( final Session session ) { // create new keyspace/tables (should not do here) TODO: move session.execute("CREATE KEYSPACE IF NOT EXISTS eucalyptus_simplequeue " + "WITH replication = {'class':'SimpleStrategy', 'replication_factor':1}; "); session.execute("USE eucalyptus_simplequeue;"); try { final String cql = Resources.toString( Resources.getResource("2017-03-03-eucalyptus-simplequeue-base.cql"), StandardCharsets.UTF_8 ); CqlUtil.splitCql( cql ).forEach( session::execute ); } catch ( final IOException | ParseException e ) { throw Exceptions.toUndeclared( e ); } } public synchronized Session getSession() { if (session == null) { initCluster(); } return session; } public static SessionProvider externalProvider( ) { return new ExternalSessionProvider( ); } public static SessionProvider internalProvider( ) { return new InternalSessionProvider( ); } public static class ChangeListener implements PropertyChangeListener { @Override public void fireChange(ConfigurableProperty t, Object newValue) throws ConfigurablePropertyException { try { external( ).initCluster((String) newValue); } catch (Exception e) { throw new ConfigurablePropertyException(e.getMessage()); } } } static interface SessionProvider { <R,E extends SimpleQueueException> R doThrowsWithSession( final ThrowingFunction<Session,R,E> callbackFunction ) throws E; <R> R doWithSession( final Function<Session,R> callbackFunction ); } static class ExternalSessionProvider implements SessionProvider { public <R,E extends SimpleQueueException> R doThrowsWithSession( final ThrowingFunction<Session,R,E> callbackFunction ) throws E { return callbackFunction.apply( CassandraSessionManager.external( ).getSession( ) ); } public <R> R doWithSession( final Function<Session,R> callbackFunction ) { return callbackFunction.apply( CassandraSessionManager.external( ).getSession( ) ); } } private static class InternalSessionProvider implements SessionProvider { public <R,E extends SimpleQueueException> R doThrowsWithSession( final ThrowingFunction<Session,R,E> callbackFunction ) throws E { return CassandraPersistence.doThrowsWithSession( "eucalyptus_simplequeue", callbackFunction ); } public <R> R doWithSession( final Function<Session,R> callbackFunction ) { return CassandraPersistence.doWithSession( "eucalyptus_simplequeue", callbackFunction ); } } }