Package com.impetus.client.cassandra.pelops

Source Code of com.impetus.client.cassandra.pelops.PelopsClientFactory

/*******************************************************************************
* * Copyright 2012 Impetus Infotech.
*  *
*  * 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
*  *
*  *      http://www.apache.org/licenses/LICENSE-2.0
*  *
*  * 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.impetus.client.cassandra.pelops;

import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Properties;

import org.scale7.cassandra.pelops.Cluster;
import org.scale7.cassandra.pelops.Cluster.Node;
import org.scale7.cassandra.pelops.IConnection;
import org.scale7.cassandra.pelops.Mutator;
import org.scale7.cassandra.pelops.Pelops;
import org.scale7.cassandra.pelops.RowDeletor;
import org.scale7.cassandra.pelops.Selector;
import org.scale7.cassandra.pelops.exceptions.TransportException;
import org.scale7.cassandra.pelops.pool.CommonsBackedPool;
import org.scale7.cassandra.pelops.pool.CommonsBackedPool.Policy;
import org.scale7.cassandra.pelops.pool.IThriftPool;
import org.scale7.cassandra.pelops.pool.IThriftPool.IPooledConnection;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.google.common.collect.Lists;
import com.impetus.client.cassandra.common.CassandraClientFactory;
import com.impetus.client.cassandra.common.CassandraUtilities;
import com.impetus.client.cassandra.config.CassandraPropertyReader;
import com.impetus.client.cassandra.query.CassandraEntityReader;
import com.impetus.client.cassandra.schemamanager.CassandraSchemaManager;
import com.impetus.client.cassandra.service.CassandraHost;
import com.impetus.client.cassandra.service.CassandraHostConfiguration;
import com.impetus.client.cassandra.service.CassandraRetryService;
import com.impetus.kundera.Constants;
import com.impetus.kundera.KunderaException;
import com.impetus.kundera.PersistenceProperties;
import com.impetus.kundera.client.Client;
import com.impetus.kundera.configure.schema.api.SchemaManager;
import com.impetus.kundera.metadata.KunderaMetadataManager;
import com.impetus.kundera.metadata.model.PersistenceUnitMetadata;
import com.impetus.kundera.service.Host;
import com.impetus.kundera.service.HostConfiguration;
import com.impetus.kundera.service.policy.LeastActiveBalancingPolicy;
import com.impetus.kundera.service.policy.RoundRobinBalancingPolicy;

/**
* A factory for creating PelopsCliobjects.
*/
public class PelopsClientFactory extends CassandraClientFactory
{
    /** The logger. */
    private static Logger logger = LoggerFactory.getLogger(PelopsClientFactory.class);

    private HostConfiguration configuration;

    @Override
    public void initialize(Map<String, Object> externalProperty)
    {
        reader = new CassandraEntityReader(kunderaMetadata);
        initializePropertyReader();
        // setExternalProperties(externalProperty);
        String loadBalancingPolicyName = CassandraPropertyReader.csmd != null ? CassandraPropertyReader.csmd
                .getConnectionProperties().getProperty(Constants.LOADBALANCING_POLICY) : null;
        initializeLoadBalancer(loadBalancingPolicyName);
        configuration = new CassandraHostConfiguration(externalProperties, CassandraPropertyReader.csmd,
                getPersistenceUnit(), kunderaMetadata);
        hostRetryService = new CassandraRetryService(configuration, this);

        // initialize timestamp generator.
        initializeTimestampGenerator(externalProperty);
    }

    @Override
    protected Object createPoolOrConnection()
    {
        logger.info("Creating pool");
        PersistenceUnitMetadata persistenceUnitMetadata = kunderaMetadata.getApplicationMetadata()
                .getPersistenceUnitMetadata(getPersistenceUnit());

        Properties props = persistenceUnitMetadata.getProperties();
        String keyspace = null;
        if (externalProperties != null)
        {
            keyspace = (String) externalProperties.get(PersistenceProperties.KUNDERA_KEYSPACE);
        }
        if (keyspace == null)
        {
            keyspace = (String) props.get(PersistenceProperties.KUNDERA_KEYSPACE);
        }

        for (Host host : ((CassandraHostConfiguration) configuration).getCassandraHosts())
        {
            CassandraHost cassandraHost = (CassandraHost) host;
            String poolName = PelopsUtils.generatePoolName(cassandraHost.getHost(), cassandraHost.getPort(), keyspace);
            if (CassandraUtilities.verifyConnection(cassandraHost.getHost(), cassandraHost.getPort()))
            {
                Cluster cluster = new Cluster(cassandraHost.getHost(), new IConnection.Config(cassandraHost.getPort(),
                        true, -1, PelopsUtils.getAuthenticationRequest(cassandraHost.getUser(),
                                cassandraHost.getPassword())), false);

                if (logger.isInfoEnabled())
                {
                    logger.info("Initializing connection pool for keyspace {}, host {},port {}.", keyspace,
                            cassandraHost.getHost(), cassandraHost.getPort());
                }

                Policy policy = PelopsUtils.getPoolConfigPolicy(cassandraHost);

                // Add pool with specified policy. null means default operand
                // policy.
                Pelops.addPool(poolName, cluster, keyspace, policy, null);
                hostPools.put(cassandraHost, Pelops.getDbConnPool(poolName));
            }
            else
            {
                logger.warn("Node " + host.getHost() + " are down");
                if (host.isRetryHost())
                {
                    logger.info("Scheduling node for future retry");
                    ((CassandraRetryService) hostRetryService).add((CassandraHost) host);
                }
            }
        }
        // TODO return a thrift pool
        return null;
    }

    @Override
    protected Client instantiateClient(String persistenceUnit)
    {
        if (logger.isInfoEnabled())
        {
            // logger.info("Initializing pelops client for persistence unit {}",
            // persistenceUnit);
        }
        IThriftPool pool = getPoolUsingPolicy();
        return new PelopsClient(indexManager, reader, this, persistenceUnit, externalProperties, pool, kunderaMetadata,
                timestampGenerator);
    }

    @Override
    public boolean isThreadSafe()
    {
        return false;
    }

    @Override
    public void destroy()
    {
        if (indexManager != null)
        {
            indexManager.close();
        }
        if (schemaManager != null)
        {
            schemaManager.dropSchema();
        }
        schemaManager = null;
        // Pelops.shutdown();
        // Pelops.removePool(PelopsUtils.generatePoolName(getPersistenceUnit(),
        // externalProperties));
        externalProperties = null;
    }

    @Override
    public SchemaManager getSchemaManager(Map<String, Object> externalProperty)
    {
        if (schemaManager == null)
        {
            initializePropertyReader();
            setExternalProperties(externalProperty);
            schemaManager = new CassandraSchemaManager(PelopsClientFactory.class.getName(), externalProperty,
                    kunderaMetadata);
        }

        return schemaManager;
    }

    /**
     *
     */
    private void initializePropertyReader()
    {
        if (propertyReader == null)
        {
            propertyReader = new CassandraPropertyReader(externalProperties, kunderaMetadata.getApplicationMetadata()
                    .getPersistenceUnitMetadata(getPersistenceUnit()));
            propertyReader.read(getPersistenceUnit());
        }
    }

    @Override
    protected void initializeLoadBalancer(String loadBalancingPolicyName)
    {
        switch (LoadBalancer.getValue(loadBalancingPolicyName))
        {
        case ROUNDROBIN:
            loadBalancingPolicy = new RoundRobinBalancingPolicy();
            break;
        case LEASTACTIVE:
            loadBalancingPolicy = new PelopsLeastActiveBalancingPolcy();
            break;
        default:
            loadBalancingPolicy = new RoundRobinBalancingPolicy();
            break;
        }
    }

    /**
     *
     * @return pool an the basis of LoadBalancing policy.
     */
    private IThriftPool getPoolUsingPolicy()
    {
        if (!hostPools.isEmpty())
        {
            logger.info("Returning pool using {} .", loadBalancingPolicy.getClass().getSimpleName());
            return (IThriftPool) loadBalancingPolicy.getPool(hostPools.values());
        }
        throw new KunderaException("All hosts are down. please check servers manully.");
    }

    IPooledConnection getConnection(IThriftPool pool)
    {
        IThriftPool iThriftPool = pool;
        boolean success = false;
        while (!success)
        {
            success = true;
            if (iThriftPool != null)
            {
                Node[] nodes = ((CommonsBackedPool) iThriftPool).getCluster().getNodes();
                String host = nodes[0].getAddress();
                int thriftPort = ((CommonsBackedPool) iThriftPool).getCluster().getConnectionConfig().getThriftPort();
                CassandraHost cassandraHost = ((CassandraHostConfiguration) configuration).getCassandraHost(
                        nodes[0].getAddress(), ((CommonsBackedPool) pool).getCluster().getConnectionConfig()
                                .getThriftPort());
                if (cassandraHost.isTestOnBorrow())
                {
                    if (cassandraHost.isTestOnBorrow() && CassandraUtilities.verifyConnection(host, thriftPort))
                    {
                        // logger.info("Returning connection of {} :{} .",
                        // nodes[0].getAddress(), thriftPort);
                        return iThriftPool.getConnection();
                    }
                    removePool(iThriftPool);
                }
                else
                {
                    // logger.info("Returning connection of {} :{} .",
                    // nodes[0].getAddress(), thriftPort);
                    return iThriftPool.getConnection();
                }
                removePool(iThriftPool);
            }
            success = false;
            iThriftPool = getPoolUsingPolicy();
        }
        throw new KunderaException("All hosts are down. please check servers manully.");
    }

    Mutator getMutator(IThriftPool pool)
    {
        IThriftPool iThriftPool = pool;
        boolean success = false;
        while (!success)
        {
            success = true;
            if (iThriftPool != null)
            {
                Node[] nodes = ((CommonsBackedPool) iThriftPool).getCluster().getNodes();
                String host = nodes[0].getAddress();
                int thriftPort = ((CommonsBackedPool) iThriftPool).getCluster().getConnectionConfig().getThriftPort();
                CassandraHost cassandraHost = ((CassandraHostConfiguration) configuration).getCassandraHost(
                        nodes[0].getAddress(), ((CommonsBackedPool) pool).getCluster().getConnectionConfig()
                                .getThriftPort());
                if (cassandraHost.isTestOnBorrow())
                {
                    if (cassandraHost.isTestOnBorrow() && CassandraUtilities.verifyConnection(host, thriftPort))
                    {
                        // logger.info("Returning mutator of {} :{} .",
                        // nodes[0].getAddress(), thriftPort);
                        return Pelops.createMutator(PelopsUtils.getPoolName(iThriftPool));
                    }
                    removePool(iThriftPool);
                }
                else
                {
                    return iThriftPool.createMutator();
                }
            }
            success = false;
            iThriftPool = getPoolUsingPolicy();
        }
        throw new KunderaException("All hosts are down. please check servers manully.");
    }

    Selector getSelector(IThriftPool pool)
    {
        IThriftPool iThriftPool = pool;
        boolean success = false;
        while (!success)
        {
            if (iThriftPool != null)
            {
                Node[] nodes = ((CommonsBackedPool) iThriftPool).getCluster().getNodes();
                String host = nodes[0].getAddress();
                int thriftPort = ((CommonsBackedPool) iThriftPool).getCluster().getConnectionConfig().getThriftPort();
                CassandraHost cassandraHost = ((CassandraHostConfiguration) configuration).getCassandraHost(
                        nodes[0].getAddress(), ((CommonsBackedPool) pool).getCluster().getConnectionConfig()
                                .getThriftPort());
                if (cassandraHost.isTestOnBorrow())
                {
                    if (cassandraHost.isTestOnBorrow() && CassandraUtilities.verifyConnection(host, thriftPort))
                    {
                        // logger.info("Returning selector of {} :{} .",
                        // nodes[0].getAddress(), thriftPort);
                        return Pelops.createSelector(PelopsUtils.getPoolName(iThriftPool));
                    }
                    removePool(iThriftPool);
                }
                else
                {
                    // logger.info("Returning selector of {} :{} .",
                    // nodes[0].getAddress(), thriftPort);
                    return Pelops.createSelector(PelopsUtils.getPoolName(iThriftPool));
                }
            }
            success = false;
            iThriftPool = getPoolUsingPolicy();
        }
        throw new KunderaException("All hosts are down. please check servers manully.");
    }

    RowDeletor getRowDeletor(IThriftPool pool)
    {
        IThriftPool iThriftPool = pool;
        boolean success = false;
        while (!success)
        {
            if (iThriftPool != null)
            {
                Node[] nodes = ((CommonsBackedPool) iThriftPool).getCluster().getNodes();
                String host = nodes[0].getAddress();
                int thriftPort = ((CommonsBackedPool) iThriftPool).getCluster().getConnectionConfig().getThriftPort();
                CassandraHost cassandraHost = ((CassandraHostConfiguration) configuration).getCassandraHost(
                        nodes[0].getAddress(), ((CommonsBackedPool) pool).getCluster().getConnectionConfig()
                                .getThriftPort());
                if (cassandraHost.isTestOnBorrow())
                {
                    if (cassandraHost.isTestOnBorrow() && CassandraUtilities.verifyConnection(host, thriftPort))
                    {
                        logger.info("Returning row deletor of {} :{} .", nodes[0].getAddress(), thriftPort);
                        return Pelops.createRowDeletor(PelopsUtils.getPoolName(iThriftPool));
                    }
                    removePool(iThriftPool);
                }
                else
                {
                    logger.info("Returning row deletor of {} :{} .", nodes[0].getAddress(), thriftPort);
                    return Pelops.createRowDeletor(PelopsUtils.getPoolName(iThriftPool));
                }
            }
            success = false;
            iThriftPool = getPoolUsingPolicy();
        }
        throw new KunderaException("All hosts are down. please check servers manully.");

    }

    void releaseConnection(IPooledConnection conn)
    {
        if (conn != null)
        {
            conn.release();
        }
    }

    /**
     * Adds a pool in hostPools map for given host.
     *
     * @param cassandraHost
     * @return true id added successfully.
     */
    public boolean addCassandraHost(CassandraHost cassandraHost)
    {
        Properties props = KunderaMetadataManager.getPersistenceUnitMetadata(kunderaMetadata, getPersistenceUnit())
                .getProperties();
        String keyspace = null;
        if (externalProperties != null)
        {
            keyspace = (String) externalProperties.get(PersistenceProperties.KUNDERA_KEYSPACE);
        }
        if (keyspace == null)
        {
            keyspace = (String) props.get(PersistenceProperties.KUNDERA_KEYSPACE);
        }
        String poolName = PelopsUtils.generatePoolName(cassandraHost.getHost(), cassandraHost.getPort(), keyspace);
        Cluster cluster = new Cluster(cassandraHost.getHost(), new IConnection.Config(cassandraHost.getPort(), true,
                -1, PelopsUtils.getAuthenticationRequest(cassandraHost.getUser(), cassandraHost.getPassword())), false);
        Policy policy = PelopsUtils.getPoolConfigPolicy(cassandraHost);
        try
        {
            Pelops.addPool(poolName, cluster, keyspace, policy, null);
            hostPools.put(cassandraHost, Pelops.getDbConnPool(poolName));
            return true;
        }
        catch (TransportException e)
        {
            logger.warn("Node {} are still down ", cassandraHost.getHost());
            return false;
        }
    }

    /**
     * Removes downed host pool from pool map.
     *
     * @param pool
     */
    private void removePool(IThriftPool pool)
    {
        Pelops.removePool(PelopsUtils.getPoolName(pool));
        Node[] nodes = ((CommonsBackedPool) pool).getCluster().getNodes();
        logger.warn("{} :{}  host appears to be down, trying for next ", nodes, ((CommonsBackedPool) pool).getCluster()
                .getConnectionConfig().getThriftPort());
        CassandraHost cassandraHost = ((CassandraHostConfiguration) configuration).getCassandraHost(
                nodes[0].getAddress(), ((CommonsBackedPool) pool).getCluster().getConnectionConfig().getThriftPort());
        hostPools.remove(cassandraHost);
    }

    /**
     * Extends LeastActiveBalancingPolicy class and provide own implementation
     * in order to support least active balancing policy.
     *
     * @author Kuldeep.Mishra
     *
     */
    private class PelopsLeastActiveBalancingPolcy extends LeastActiveBalancingPolicy
    {

        /**
         *
         * @return pool object for host which has least active connections
         *         determined by maxActive connection.
         *
         */
        public Object getPool(Collection<Object> pools)
        {
            List<Object> vals = Lists.newArrayList(pools);
            Collections.shuffle(vals);
            Collections.sort(vals, new ShufflingCompare());
            Collections.reverse(vals);
            Iterator<Object> iterator = vals.iterator();
            Object concurrentConnectionPool = iterator.next();
            return concurrentConnectionPool;
        }

        /**
         * Compares two pool object on the basis of their maxActive connection
         * per node.
         *
         * @author Kuldeep Mishra
         *
         */
        private final class ShufflingCompare implements Comparator<Object>
        {
            public int compare(Object o1, Object o2)
            {
                Policy policy1 = ((CommonsBackedPool) ((IThriftPool) o1)).getPolicy();
                Policy policy2 = ((CommonsBackedPool) ((IThriftPool) o2)).getPolicy();

                int activeConnections1 = ((CommonsBackedPool) ((IThriftPool) o1)).getConnectionsActive();
                int activeConnections2 = ((CommonsBackedPool) ((IThriftPool) o2)).getConnectionsActive();

                return (policy1.getMaxActivePerNode() - activeConnections1)
                        - (policy2.getMaxActivePerNode() - activeConnections2);
            }
        }
    }
}
TOP

Related Classes of com.impetus.client.cassandra.pelops.PelopsClientFactory

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.