net.sheehantech.cherry.pool.KeyedPooledPushClient.java Source code

Java tutorial

Introduction

Here is the source code for net.sheehantech.cherry.pool.KeyedPooledPushClient.java

Source

/*
 * This file is part of Cherry.
 *
 * Cherry is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Cherry 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 Lesser General Public License
 * along with Cherry.  If not, see <http://www.gnu.org/licenses/>.
 *
 */

package net.sheehantech.cherry.pool;

import net.sheehantech.cherry.*;
import org.apache.commons.pool2.impl.GenericKeyedObjectPool;
import org.apache.commons.pool2.impl.GenericKeyedObjectPoolConfig;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.net.ssl.SSLContext;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

public class KeyedPooledPushClient<K> extends AbstractKeyedPushClient<K> {

    private Logger logger = LoggerFactory.getLogger(KeyedPooledPushClient.class);

    private GenericKeyedObjectPool<K, PooledPushSocket> pool;
    private Integer maxTotal;
    private Integer maxIdle;
    private Integer minIdle;
    private ExecutorService executor;

    public KeyedPooledPushClient(Map<K, SSLContext> sslContexts, Map<K, String> gateways, Map<K, Integer> ports) {
        super(sslContexts, gateways, ports);
        executor = Executors.newCachedThreadPool();
    }

    public Integer getMaxTotal() {
        return maxTotal;
    }

    public void setMaxTotal(Integer maxTotal) {
        this.maxTotal = maxTotal;
    }

    public Integer getMaxIdle() {
        return maxIdle;
    }

    public void setMaxIdle(Integer maxIdle) {
        this.maxIdle = maxIdle;
    }

    public Integer getMinIdle() {
        return minIdle;
    }

    public void setMinIdle(Integer minIdle) {
        this.minIdle = minIdle;
    }

    @Override
    public void init() throws ConnectionFailedException {
        GenericKeyedObjectPoolConfig config = new GenericKeyedObjectPoolConfig();
        if (maxTotal != null)
            config.setMaxTotalPerKey(maxTotal);
        if (maxIdle != null)
            config.setMaxIdlePerKey(maxIdle);
        if (minIdle != null)
            config.setMinIdlePerKey(minIdle);
        config.setTestOnBorrow(true);
        config.setTestWhileIdle(true);
        config.setBlockWhenExhausted(true);
        config.setMaxTotalPerKey(maxTotal);
        pool = new GenericKeyedObjectPool<K, PooledPushSocket>(
                new KeyedPooledPushSocketFactory(socketFactories, gateways, ports), config);
        try {
            for (K k : sslContexts.keySet())
                pool.preparePool(k);
        } catch (Exception e) {
            throw (new ConnectionFailedException(e));
        }
        logger.debug("Started new push socket pool with {} sockets", pool.getNumIdle());

    }

    @Override
    public Future<PushResult> send(Notification notification) throws PushFailedException, ProtocolException {
        throw (new PushFailedException());
    }

    @Override
    public KeyedNotificationBuilder<K> newNotification() {
        return null;
    }

    @Override
    public KeyedNotificationBuilder<K> newNotification(K k) {
        return (new KeyedNotificationBuilder<K>(this, k));
    }

    @Override
    public Future<PushResult> send(Notification notification, K k) throws PushFailedException, ProtocolException {
        try {
            notification.setId(nextId());
            Future<PushResult> pushResultFuture = executor
                    .submit(new KeyedPooledSendNotificationTask(pool, k, notification));
            logger.debug("Sent notification {}", notification.getId());
            return pushResultFuture;
        } catch (Exception e) {
            throw (new PushFailedException(e));
        }
    }

    @Override
    public void shutdown() {
        while (!pool.isClosed()) {
            if (pool.getNumActive() == 0) {
                pool.close();
                logger.info("Shut down pool");
            } else {
                try {
                    logger.debug("Waiting for {} active sockets", pool.getNumActive());
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    logger.debug("Interrrupted during graceful shutdown");
                }
            }
        }
    }

    @Override
    public void shutdownNow() {
        pool.close();
    }
}