Package org.redisson.connection

Source Code of org.redisson.connection.PubSubConnectionEntry

/**
* Copyright 2014 Nikita Koksharov, Nickolay Borbit
*
* 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 org.redisson.connection;

import io.netty.util.concurrent.Future;
import io.netty.util.concurrent.FutureListener;

import java.util.Collection;
import java.util.Collections;
import java.util.Queue;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.Semaphore;

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

import com.lambdaworks.redis.pubsub.RedisPubSubAdapter;
import com.lambdaworks.redis.pubsub.RedisPubSubConnection;
import com.lambdaworks.redis.pubsub.RedisPubSubListener;

public class PubSubConnectionEntry {

    public enum Status {ACTIVE, INACTIVE}

    private final Logger log = LoggerFactory.getLogger(getClass());

    private volatile Status status = Status.ACTIVE;
    private final Semaphore subscribedChannelsAmount;
    private final RedisPubSubConnection conn;
    private final int subscriptionsPerConnection;
    private final ConcurrentMap<String, Queue<RedisPubSubListener>> channelListeners = new ConcurrentHashMap<String, Queue<RedisPubSubListener>>();

    public PubSubConnectionEntry(RedisPubSubConnection conn, int subscriptionsPerConnection) {
        super();
        this.conn = conn;
        this.subscriptionsPerConnection = subscriptionsPerConnection;
        this.subscribedChannelsAmount = new Semaphore(subscriptionsPerConnection);
    }

    public Collection<RedisPubSubListener> getListeners(String channelName) {
        Collection<RedisPubSubListener> result = channelListeners.get(channelName);
        if (result == null) {
            return Collections.emptyList();
        }
        return result;
    }
   
    public void addListener(String channelName, RedisPubSubListener listener) {
        Queue<RedisPubSubListener> queue = channelListeners.get(channelName);
        if (queue == null) {
            queue = new ConcurrentLinkedQueue<RedisPubSubListener>();
            Queue<RedisPubSubListener> oldQueue = channelListeners.putIfAbsent(channelName, queue);
            if (oldQueue != null) {
                queue = oldQueue;
            }
        }

        synchronized (queue) {
            if (channelListeners.get(channelName) != queue) {
                addListener(channelName, listener);
                return;
            }
            queue.add(listener);
        }
       
        conn.addListener(listener);
    }

    public boolean isActive() {
        return status == Status.ACTIVE;
    }

    public void close() {
        status = Status.INACTIVE;
    }

    // TODO optimize
    public void removeListener(String channelName, int listenerId) {
        Queue<RedisPubSubListener> listeners = channelListeners.get(channelName);
        for (RedisPubSubListener listener : listeners) {
            if (listener.hashCode() == listenerId) {
                removeListener(channelName, listener);
                break;
            }
        }
    }

    public void removeListener(String channelName, RedisPubSubListener listener) {
        Queue<RedisPubSubListener> queue = channelListeners.get(channelName);
        synchronized (queue) {
            if (queue.remove(listener)) {
                channelListeners.remove(channelName, new ConcurrentLinkedQueue<RedisPubSubListener>());
            }
        }
        conn.removeListener(listener);
    }

    public boolean tryAcquire() {
        return subscribedChannelsAmount.tryAcquire();
    }

    public void release() {
        subscribedChannelsAmount.release();
    }

    public void subscribe(final String channelName) {
        conn.addListener(new RedisPubSubAdapter() {
            @Override
            public void subscribed(String channel, long count) {
                log.debug("subscribed to '{}' channel", channelName);
            }

            @Override
            public void unsubscribed(String channel, long count) {
                log.debug("unsubscribed from '{}' channel", channelName);
            }
        });
        conn.subscribe(channelName);
    }


    public void subscribe(RedisPubSubAdapter listener, String channel) {
        addListener(channel, listener);
        conn.subscribe(channel);
    }

    public Future unsubscribe(final String channel) {
        Queue<RedisPubSubListener> listeners = channelListeners.get(channel);
        if (listeners != null) {
            for (RedisPubSubListener listener : listeners) {
                removeListener(channel, listener);
            }
        }

        Future future = conn.unsubscribe(channel);
        future.addListener(new FutureListener() {
            @Override
            public void operationComplete(Future future) throws Exception {
                subscribedChannelsAmount.release();
            }
        });
        return future;
    }

    public boolean tryClose() {
        if (subscribedChannelsAmount.tryAcquire(subscriptionsPerConnection)) {
            close();
            return true;
        }
        return false;
    }

    public RedisPubSubConnection getConnection() {
        return conn;
    }

}
TOP

Related Classes of org.redisson.connection.PubSubConnectionEntry

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.