Package redis.clients.jedis

Source Code of redis.clients.jedis.JedisClusterCommand

package redis.clients.jedis;

import redis.clients.jedis.exceptions.JedisAskDataException;
import redis.clients.jedis.exceptions.JedisClusterException;
import redis.clients.jedis.exceptions.JedisClusterMaxRedirectionsException;
import redis.clients.jedis.exceptions.JedisConnectionException;
import redis.clients.jedis.exceptions.JedisMovedDataException;
import redis.clients.jedis.exceptions.JedisRedirectionException;
import redis.clients.util.JedisClusterCRC16;

public abstract class JedisClusterCommand<T> {

    private JedisClusterConnectionHandler connectionHandler;
    private int commandTimeout;
    private int redirections;
    private ThreadLocal<Jedis> askConnection = new ThreadLocal<Jedis>();

    public JedisClusterCommand(JedisClusterConnectionHandler connectionHandler,
      int timeout, int maxRedirections) {
  this.connectionHandler = connectionHandler;
  this.commandTimeout = timeout;
  this.redirections = maxRedirections;
    }

    public abstract T execute(Jedis connection);

    public T run(String key) {
  if (key == null) {
      throw new JedisClusterException(
        "No way to dispatch this command to Redis Cluster.");
  }

  return runWithRetries(key, this.redirections, false, false);
    }

    private T runWithRetries(String key, int redirections,
      boolean tryRandomNode, boolean asking) {
  if (redirections <= 0) {
      throw new JedisClusterMaxRedirectionsException(
        "Too many Cluster redirections?");
  }

  Jedis connection = null;
  try {

      if (asking) {
    // TODO: Pipeline asking with the original command to make it
    // faster....
    connection = askConnection.get();
    connection.asking();

    // if asking success, reset asking flag
    asking = false;
      } else {
    if (tryRandomNode) {
        connection = connectionHandler.getConnection();
    } else {
        connection = connectionHandler
          .getConnectionFromSlot(JedisClusterCRC16
            .getSlot(key));
    }
      }

      return execute(connection);
  } catch (JedisConnectionException jce) {
      if (tryRandomNode) {
    // maybe all connection is down
    throw jce;
      }

      releaseConnection(connection, true);
      connection = null;

      // retry with random connection
      return runWithRetries(key, redirections - 1, true, asking);
  } catch (JedisRedirectionException jre) {
      if (jre instanceof JedisAskDataException) {
    asking = true;
    askConnection.set(this.connectionHandler
      .getConnectionFromNode(jre.getTargetNode()));
      } else if (jre instanceof JedisMovedDataException) {
    // it rebuilds cluster's slot cache
    // recommended by Redis cluster specification
    this.connectionHandler.renewSlotCache();
      } else {
    throw new JedisClusterException(jre);
      }

      releaseConnection(connection, false);
      connection = null;

      return runWithRetries(key, redirections - 1, false, asking);
  } finally {
      releaseConnection(connection, false);
  }

    }

    private void releaseConnection(Jedis connection, boolean broken) {
  if (connection != null) {
      if (broken) {
    connectionHandler.returnBrokenConnection(connection);
      } else {
    connectionHandler.returnConnection(connection);
      }
  }
    }

}
TOP

Related Classes of redis.clients.jedis.JedisClusterCommand

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.