Package ch.uzh.ifi.ddis.ifp.esper.cassandra

Source Code of ch.uzh.ifi.ddis.ifp.esper.cassandra.CassandraVirtualDataWindowFactory

package ch.uzh.ifi.ddis.ifp.esper.cassandra;

/*
* #%L
* Cassandra for Esper
* %%
* Copyright (C) 2013 University of Zurich
* %%
* 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, either version 2 of the
* License, or (at your option) any later version.
*
* 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/gpl-2.0.html>.
* #L%
*/

import java.util.Properties;
import java.util.Set;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.datastax.driver.core.Cluster;
import com.datastax.driver.core.Cluster.Builder;
import com.datastax.driver.core.Session;
import com.datastax.driver.core.exceptions.AlreadyExistsException;
import com.datastax.driver.core.exceptions.InvalidQueryException;
import com.espertech.esper.client.hook.VirtualDataWindowContext;
import com.espertech.esper.client.hook.VirtualDataWindowFactory;
import com.espertech.esper.client.hook.VirtualDataWindowFactoryContext;

/**
* <p>
* Factory for creating {@link CassandraVirtualDataWindow} objects.
* </p>
*
* @author Thomas Scharrenbach
* @version 0.2.3
* @since 0.0.1
*
*/
public class CassandraVirtualDataWindowFactory implements
    VirtualDataWindowFactory {

  private static final Logger _log = LoggerFactory
      .getLogger(CassandraVirtualDataWindowFactory.class);

  //
  //
  //

  /**
   * Key for the system {@link Properties}, which stores the username for
   * authenticating to Cassandra. Can be overridden by the configuration.
   */
  public static final String CASSANDRA_USERNAME = "cassandra-username";

  /**
   * Key for the system {@link Properties}, which stores the root username for
   * authenticating to Cassandra. Can be overridden by the configuration.
   */
  public static final String CASSANDRA_ROOT_USERNAME = "cassandra-root-username";

  /**
   * Key for the system {@link Properties}, which stores the password for
   * authenticating to Cassandra. Can be overridden by the configuration.
   */
  public static final String CASSANDRA_PASSWORD = "cassandra-password";

  /**
   * Key for the system {@link Properties}, which stores the password for
   * authenticating to Cassandra. Can be overridden by the configuration.
   */
  public static final String CASSANDRA_ROOT_PASSWORD = "cassandra-root-password";

  //
  //
  //

  /**
   * Connection for SELECT, INSERT, and UPDATE.
   */
  private Cluster _cluster;

  /**
   * Connection for creating the keyspace, the table and granting access
   * rights.
   */
  private Cluster _rootCluster;

  private CassandraConfiguration _configuration;

  /**
   * Stores the user which performs SELECT, INSERT, and UPDATE queries.
   */
  private String _username;

  //
  //
  //

  public CassandraVirtualDataWindowFactory() {
    return;
  }

  //
  //
  //

  private Cluster connectToCluster(String node, String username,
      String password) throws Exception {
    Builder clusterBuilder = Cluster.builder().withoutMetrics();

    Cluster cluster = null;
    try {
      _log.info("Started connecting to cluster: {} ...", node);
      _log.debug("Adding contact point...");
      clusterBuilder = clusterBuilder.addContactPoint(node);

      if (username != null && password != null) {
        _log.debug("Adding credentials...");
        clusterBuilder = clusterBuilder.withCredentials(username,
            password);
      }

      _log.debug("Building cluster user...");
      cluster = clusterBuilder.build();

      _log.info("Finished connecting to cluster user: {} .", node);

    } catch (Exception e) {
      _log.error("Error connecting to cluster user: {} !", node);

      final String errorMessage = String.format(
          "Could not connect to Cassandra cluster!", node);
      throw new Exception(errorMessage, e);
    }
    return cluster;

  }

  private void createKeyspace(String node, String keyspace) throws Exception {

    Session session = null;
    Exception error = null;
    try {
      _log.info("Started checking whether keyspace {} exists...",
          keyspace);
      session = _rootCluster.connect(keyspace);
      _log.info("Finished checking whether keyspace {} exists...",
          keyspace);
      _log.info("Keyspace {} exists, nothing to do.", keyspace);
    }
    // Keyspace does not exist, so session is not null...
    catch (AlreadyExistsException ae) {
    }
    // Keyspace does not exist, so we try to create it.
    // In that case, session is null
    catch (InvalidQueryException ae) {
    }
    // Unknown exception -> error
    catch (Exception e) {
      _log.error("Unexcpected Exception when checking for keyspace {}!",
          keyspace, e);
      error = e;
    }

    if (session == null && error == null) {
      _log.info("Finished checking whether keyspace {} exists...",
          keyspace);
      _log.info("Keyspace does not yet {} exist, trying to create it",
          keyspace);
      try {
        _log.info("Started creating keyspace {} ...", keyspace);
        session = _rootCluster.connect();

        final String query = String.format("" + "CREATE keyspace %s "
            + "WITH replication = "
            + "{'class': 'SimpleStrategy', "
            + "'replication_factor' : 3}", keyspace);
        session.execute(query);
        _log.info("Finished creating keyspace {} .", keyspace);
      } catch (Exception e) {
        _log.error("Error creating keyspace {}", keyspace, e);
        error = e;
      }
      // In any case, shut down the session for the root user.
      finally {
        if (session != null) {
          _log.info("Started shutting down session for creating keyspace ...");
          session.shutdown();
          _log.info("Finished shutting down session for creating keyspace.");
        }
      }
    }
    if (error != null) {
      throw error;
    }

  }

  private void createTable(VirtualDataWindowContext context) throws Exception {

    Session session = null;
    Exception error = null;
    final String table = context.getNamedWindowName();
    final String keyspace = context.getViewFactoryContext()
        .getNamespaceName();

    boolean tableExists = true;
    try {
      _log.info("Started checking whether table {} exists...", table);
      session = _rootCluster.connect(keyspace);
      session.execute(String.format("SELECT * FROM %s LIMIT 10", table));

      _log.info("Finished checking whether table {} exists...", table);
      _log.info("Table {} exists, nothing to do.", table);
    }
    // Keyspace does not exist, so we try to create it.
    catch (InvalidQueryException ae) {
      tableExists = false;
    }
    // Unknown exception -> error
    catch (Exception e) {
      tableExists = false;
      _log.error("Unexcpected Exception when checking for table {}!",
          table, e);
      error = e;
    }

    if (error == null) {
      _log.info("Finished checking whether table {} exists...", table);
      try {
        session = _rootCluster.connect(keyspace);
        if (!tableExists) {
          _log.info(
              "Table does not yet {} exist, trying to create it",
              table);

          try {
            _log.info("Started creating table {} ...", table);
            final String createQuery = QueryStringBuilder
                .createCreateTableQuery(context);
            _log.debug("Executing create query: {}", createQuery);
            session.execute(createQuery);
            _log.info("Finished creating table {} .", table);
          } catch (Exception e) {
            _log.error("Error creating table {} .", table);
            error = e;
          }
        }

        if (_username != null && error == null) {
          try {
            _log.info("Started granting rights to table {} ...",
                table);
            final String grantQuery = String.format(
                "GRANT ALL on %s TO %s", table, _username);
            _log.debug("Executing grant query: {}", grantQuery);
            session.execute(grantQuery);
            _log.info("Finished granting rights to table {}.",
                table);
          } catch (Exception e) {
            _log.error("Error granting rights to table {}.", table,
                e);
            error = e;
          }
        }

      } catch (Exception e) {
        _log.error("Error creating table {}", table, e);
        error = e;
      }
      // In any case, shut down the session for the root user.
      finally {
        if (session != null) {
          _log.info("Started shutting down session for creating table ...");
          session.shutdown();
          _log.info("Finished shutting down session for creating table.");
        }
      }
    }
    if (error != null) {
      throw error;
    }

  }

  //
  //
  //

  /**
   * <p>
   * Initializes the Cassandra {@link Cluster}.
   * </p>
   *
   * @throws java.lang.RuntimeException
   *             In case the connection to Cassandra fails.
   */
  @Override
  public void initialize(VirtualDataWindowFactoryContext factoryContext) {
    final String keyspace = factoryContext.getViewFactoryContext()
        .getNamespaceName();
    final Object[] windowParameters = factoryContext.getParameters();

    if (windowParameters.length < 1) {
      throw new RuntimeException(String.format(
          "Cassandra window has at least one parameter. "
              + "Found %s", windowParameters.length));
    }

    final String parameter = windowParameters[0].toString().trim();

    _log.info("Started parsing Cassandra configuration...");
    try {
      _configuration = CassandraConfiguration.create(parameter);
    } catch (Exception pe) {
      _log.error("Error parsing Cassandra configuration!");
      throw new RuntimeException(pe);
    }
    _log.info("Finished parsing Cassandra configuration.");

    final String node = _configuration.getHost();
    _username = System.getProperty(CASSANDRA_USERNAME, null);
    final String password = System.getProperty(CASSANDRA_PASSWORD, null);
    final String rootUsername = System.getProperty(CASSANDRA_ROOT_USERNAME,
        null);
    final String rootPassword = System.getProperty(CASSANDRA_ROOT_PASSWORD,
        null);
    try {
      _rootCluster = connectToCluster(node, rootUsername, rootPassword);
      createKeyspace(node, keyspace);
      _cluster = connectToCluster(node, _username, password);
    } catch (Exception e) {
      throw new RuntimeException(e);
    }
  }

  /**
   * <p>
   * Creates a new {@link CassandraVirtualDataWindow} by creating a Cassandra
   * {@link Session}.
   * </p>
   * <p>
   * <strong>Note: This method is thread-safe.</strong>
   * </p>
   *
   * @throws RuntimeException
   *             In case the cluster is null or the creation of the session
   *             fails.
   */
  @Override
  public CassandraVirtualDataWindow create(VirtualDataWindowContext context) {
    if (_cluster == null) {
      throw new RuntimeException(
          "Cassandra cluster has not yet been initialized!");
    }
    CassandraVirtualDataWindow result = null;
    synchronized (_cluster) {
      try {
        _log.info("Started connecting to cluster...");
        final Session session = _cluster.connect(_configuration
            .getKeyspace());
        _log.info("Finished connecting to cluster...");

        createTable(context);

        result = new CassandraVirtualDataWindow(session,
            context.getNamedWindowName(), context);
      } catch (Exception e) {
        _log.error("Error connecting to cluster!");
        throw new RuntimeException(e);
      }
    }
    return result;
  }

  /**
   * <p>
   * Shuts down the connection to the Cassandra {@link Cluster}.
   * </p>
   */
  @Override
  public void destroyAllContextPartitions() {
    close();
  }

  /**
   * @return null.
   */
  @Override
  public Set<String> getUniqueKeyPropertyNames() {
    return null;
  }

  //
  //
  //

  /**
   * <p>
   * Disconnect from Cassandra {@link Cluster}.
   * </p>
   */
  protected void close() {
    try {
      _log.info("Started shutting down connection to Cassandra cluster...");
      if (_cluster != null) {
        _cluster.shutdown();
      }
      _log.info("Finished shutting down connection to Cassandra cluster.");
    }
    //
    catch (Exception e) {
      _log.error("Error shutting down connection to Cassandra cluster!",
          e);
    }
    try {
      _log.info("Started shutting down connection to Cassandra root cluster...");
      if (_cluster != null) {
        _rootCluster.shutdown();
      }
      _log.info("Finished shutting down connection to Cassandra root cluster.");
    }
    //
    catch (Exception e) {
      _log.error(
          "Error shutting down connection to Cassandra root cluster!",
          e);
    }
  }

}
TOP

Related Classes of ch.uzh.ifi.ddis.ifp.esper.cassandra.CassandraVirtualDataWindowFactory

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.