Package org.redisson.connection

Source Code of org.redisson.connection.MasterSlaveEntry

/**
* 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.channel.EventLoopGroup;

import java.net.URI;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

import org.redisson.MasterSlaveServersConfig;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.lambdaworks.redis.RedisClient;
import com.lambdaworks.redis.RedisConnection;
import com.lambdaworks.redis.RedisConnectionException;
import com.lambdaworks.redis.codec.RedisCodec;
import com.lambdaworks.redis.pubsub.RedisPubSubConnection;

/**
*
* @author Nikita Koksharov
*
*/
//TODO ping support
public class MasterSlaveEntry {

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

    LoadBalancer slaveBalancer;
    volatile ConnectionEntry masterEntry;

    final MasterSlaveServersConfig config;
    final RedisCodec codec;
    final EventLoopGroup group;

    public MasterSlaveEntry(RedisCodec codec, EventLoopGroup group, MasterSlaveServersConfig config) {
        this.codec = codec;
        this.group = group;
        this.config = config;

        slaveBalancer = config.getLoadBalancer();
        slaveBalancer.init(codec, config);

        List<URI> addresses = new ArrayList<URI>(config.getSlaveAddresses());
        addresses.add(config.getMasterAddress());
        for (URI address : addresses) {
            RedisClient client = new RedisClient(group, address.getHost(), address.getPort(), config.getTimeout());
            SubscribesConnectionEntry entry = new SubscribesConnectionEntry(client,
                    config.getSlaveConnectionPoolSize(),
                    config.getSlaveSubscriptionConnectionPoolSize());
            slaveBalancer.add(entry);
        }
        if (config.getSlaveAddresses().size() > 1) {
            slaveDown(config.getMasterAddress().getHost(), config.getMasterAddress().getPort());
        }

        setupMasterEntry(config.getMasterAddress().getHost(), config.getMasterAddress().getPort());
    }

    public void setupMasterEntry(String host, int port) {
        RedisClient masterClient = new RedisClient(group, host, port, config.getTimeout());
        masterEntry = new ConnectionEntry(masterClient, config.getMasterConnectionPoolSize());
    }

    public Collection<RedisPubSubConnection> slaveDown(String host, int port) {
        return slaveBalancer.freeze(host, port);
    }

    public void addSlave(String host, int port) {
        slaveDown(masterEntry.getClient().getAddr().getHostName(), masterEntry.getClient().getAddr().getPort());

        RedisClient client = new RedisClient(group, host, port, config.getTimeout());
        slaveBalancer.add(new SubscribesConnectionEntry(client,
                this.config.getSlaveConnectionPoolSize(),
                this.config.getSlaveSubscriptionConnectionPoolSize()));
    }

    public void slaveUp(String host, int port) {
        slaveBalancer.unfreeze(host, port);
    }

    /**
     * Freeze slave with <code>host:port</code> from slaves list.
     * Re-attach pub/sub listeners from it to other slave.
     * Shutdown old master client.
     *
     */
    public void changeMaster(String host, int port) {
        ConnectionEntry oldMaster = masterEntry;
        setupMasterEntry(host, port);
        slaveDown(host, port);
        oldMaster.getClient().shutdown();
    }

    public <K, V> RedisConnection<K, V> connectionWriteOp() {
        acquireMasterConnection();

        RedisConnection<K, V> conn = masterEntry.getConnections().poll();
        if (conn != null) {
            return conn;
        }

        try {
            conn = masterEntry.getClient().connect(codec);
            if (config.getPassword() != null) {
                conn.auth(config.getPassword());
            }
            if (config.getDatabase() != 0) {
                conn.select(config.getDatabase());
            }
            return conn;
        } catch (RedisConnectionException e) {
            masterEntry.getConnectionsSemaphore().release();
            throw e;
        }
    }

    public <K, V> RedisConnection<K, V> connectionReadOp() {
        return slaveBalancer.nextConnection();
    }

    RedisPubSubConnection nextPubSubConnection() {
        return slaveBalancer.nextPubSubConnection();
    }

    void acquireMasterConnection() {
        if (!masterEntry.getConnectionsSemaphore().tryAcquire()) {
            log.warn("Master connection pool gets exhausted! Trying to acquire connection ...");
            long time = System.currentTimeMillis();
            masterEntry.getConnectionsSemaphore().acquireUninterruptibly();
            long endTime = System.currentTimeMillis() - time;
            log.warn("Master connection acquired, time spended: {} ms", endTime);
        }
    }

    public void returnSubscribeConnection(PubSubConnectionEntry entry) {
        slaveBalancer.returnSubscribeConnection(entry.getConnection());
    }

    public void releaseWrite(RedisConnection connection) {
        // may changed during changeMaster call
        if (!masterEntry.getClient().equals(connection.getRedisClient())) {
            connection.close();
            return;
        }

        masterEntry.getConnections().add(connection);
        masterEntry.getConnectionsSemaphore().release();
    }

    public void releaseRead(RedisConnection сonnection) {
        slaveBalancer.returnConnection(сonnection);
    }

    public void shutdown() {
        masterEntry.getClient().shutdown();
        slaveBalancer.shutdown();
    }

}
TOP

Related Classes of org.redisson.connection.MasterSlaveEntry

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.