Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
/*******************************************************************************
* Copyright 2011 Netflix
*
* 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.netflix.dyno.jedis;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Strings;
import com.netflix.discovery.DiscoveryClient;
import com.netflix.discovery.EurekaClient;
import com.netflix.dyno.connectionpool.*;
import com.netflix.dyno.connectionpool.exception.DynoConnectException;
import com.netflix.dyno.connectionpool.exception.DynoException;
import com.netflix.dyno.connectionpool.exception.NoAvailableHostsException;
import com.netflix.dyno.connectionpool.impl.ConnectionPoolConfigurationImpl;
import com.netflix.dyno.connectionpool.impl.ConnectionPoolImpl;
import com.netflix.dyno.connectionpool.impl.lb.HostToken;
import com.netflix.dyno.connectionpool.impl.lb.HttpEndpointBasedTokenMapSupplier;
import com.netflix.dyno.connectionpool.impl.utils.CollectionUtils;
import com.netflix.dyno.connectionpool.impl.utils.ZipUtils;
import com.netflix.dyno.contrib.ArchaiusConnectionPoolConfiguration;
import com.netflix.dyno.contrib.DynoCPMonitor;
import com.netflix.dyno.contrib.DynoOPMonitor;
import com.netflix.dyno.contrib.EurekaHostsSupplier;
import lombok.AllArgsConstructor;
import lombok.Getter;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.tuple.Pair;
import org.slf4j.Logger;
import redis.clients.jedis.*;
import redis.clients.jedis.commands.*;
import redis.clients.jedis.params.GeoRadiusParam;
import redis.clients.jedis.params.SetParams;
import redis.clients.jedis.params.ZAddParams;
import redis.clients.jedis.params.ZIncrByParams;
import javax.net.ssl.SSLSocketFactory;
import java.io.IOException;
import java.util.*;
import java.util.Map.Entry;
import java.util.concurrent.atomic.AtomicReference;
import static com.netflix.dyno.connectionpool.ConnectionPoolConfiguration.CompressionStrategy;
public class DynoJedisClient implements JedisCommands, BinaryJedisCommands, MultiKeyCommands,
ScriptingCommands, MultiKeyBinaryCommands, DynoJedisCommands {
private static final Logger Logger = org.slf4j.LoggerFactory.getLogger(DynoJedisClient.class);
private static final String DYNO_EXIPREHASH_METADATA_KEYPREFIX = "_metadata:";
private final String appName;
private final String clusterName;
private final ConnectionPool connPool;
private final AtomicReference pipelineMonitor = new AtomicReference();
protected final DynoOPMonitor opMonitor;
protected final ConnectionPoolMonitor cpMonitor;
public DynoJedisClient(String name, String clusterName, ConnectionPool pool, DynoOPMonitor operationMonitor,
ConnectionPoolMonitor cpMonitor) {
this.appName = name;
this.clusterName = clusterName;
this.connPool = pool;
this.opMonitor = operationMonitor;
this.cpMonitor = cpMonitor;
}
public ConnectionPoolImpl getConnPool() {
return (ConnectionPoolImpl) connPool;
}
public String getApplicationName() {
return appName;
}
public String getClusterName() {
return clusterName;
}
private abstract class BaseKeyOperation implements Operation {
private final String key;
private final byte[] binaryKey;
private final OpName op;
private BaseKeyOperation(final String k, final OpName o) {
this.key = k;
this.binaryKey = null;
this.op = o;
}
private BaseKeyOperation(final byte[] k, final OpName o) {
this.key = null;
this.binaryKey = k;
this.op = o;
}
@Override
public String getName() {
return op.name();
}
@Override
public String getStringKey() {
return this.key;
}
public byte[] getBinaryKey() {
return this.binaryKey;
}
}
/**
* A poor man's solution for multikey operation. This is similar to
* basekeyoperation just that it takes a list of keys as arguments. For
* token aware, we just use the first key in the list. Ideally we should be
* doing a scatter gather
*/
private abstract class MultiKeyOperation implements Operation {
private final List keys;
private final List binaryKeys;
private final OpName op;
private MultiKeyOperation(final List keys, final OpName o) {
Object firstKey = (keys != null && keys.size() > 0) ? keys.get(0) : null;
if (firstKey != null) {
if (firstKey instanceof String) {//string key
this.keys = keys;
this.binaryKeys = null;
} else if (firstKey instanceof byte[]) {//binary key
this.keys = null;
this.binaryKeys = keys;
} else {//something went wrong here
this.keys = null;
this.binaryKeys = null;
}
} else {
this.keys = null;
this.binaryKeys = null;
}
this.op = o;
}
@Override
public String getName() {
return op.name();
}
@Override
public String getStringKey() {
return (this.keys != null) ? this.keys.get(0) : null;
}
public byte[] getBinaryKey() {
return (binaryKeys != null) ? binaryKeys.get(0) : null;
}
}
/**
* The following commands are supported
*
*
* String Operations
*
{@link #get(String) GET}
*
{@link #getSet(String, String) GETSET}
*
{@link #set(String, String) SET}
*
{@link #setex(String, int, String) SETEX}
*
{@link #psetex(String, long, String) PSETEX)
*
*
* Hash Operations
*
{@link #hget(String, String) HGET}
*
{@link #hgetAll(String) HGETALL}
*
{@link #hmget(String, String...) HMGET}
*
{@link #hmset(String, Map) HMSET}
*
{@link #hscan(String, String) HSCAN}
*
{@link #hset(String, String, String) HSET}
*
{@link #hsetnx(String, String, String) HSETNX}
*
{@link #hvals(String) HVALS}
*
*
*
*
{@link #get(byte[]) GET}
*
{@link #set(byte[], byte[]) SET}
*
{@link #setex(byte[], int, byte[]) SETEX}
*
*
* @param the parameterized type
*/
private abstract class CompressionValueOperation extends BaseKeyOperation
implements CompressionOperation {
private CompressionValueOperation(String k, OpName o) {
super(k, o);
}
/**
* Compresses the value based on the threshold defined by
* {@link ConnectionPoolConfiguration#getValueCompressionThreshold()}
*
* @param value
* @return
*/
@Override
public String compressValue(String value, ConnectionContext ctx) {
String result = value;
int thresholdBytes = connPool.getConfiguration().getValueCompressionThreshold();
try {
// prefer speed over accuracy here so rather than using
// getBytes() to get the actual size
// just estimate using 2 bytes per character
if ((2 * value.length()) > thresholdBytes) {
result = ZipUtils.compressStringToBase64String(value);
ctx.setMetadata("compression", true);
}
} catch (IOException e) {
Logger.warn(
"UNABLE to compress [" + value + "] for key [" + getStringKey() + "]; sending value uncompressed");
}
return result;
}
@Override
public String decompressValue(String value, ConnectionContext ctx) {
try {
if (ZipUtils.isCompressed(value)) {
ctx.setMetadata("decompression", true);
return ZipUtils.decompressFromBase64String(value);
}
} catch (IOException e) {
Logger.warn("Unable to decompress value [" + value + "]");
}
return value;
}
}
/**
* The following commands are supported
*
*
* String Operations
*
{@link #mget(String...) MGET}
*
{@link #mset(String...) MSET}
*
{@link #msetnx(String...) MSETNX}
*
*
* @param the parameterized type
*/
private abstract class CompressionValueMultiKeyOperation extends MultiKeyOperation
implements MultiKeyCompressionOperation {
private CompressionValueMultiKeyOperation(List keys, OpName o) {
super(keys, o);
}
/**
* Accepts a set of keys and values and compresses the value based on the threshold defined by
* {@link ConnectionPoolConfiguration#getValueCompressionThreshold()}
*
* @param ctx and keyValues
* @return
*/
@Override
public String[] compressMultiKeyValue(ConnectionContext ctx, String... keyValues) {
List items = Arrays.asList(keyValues);
List newItems = new ArrayList();
for (int i = 0; i < items.size(); i++) {
/*
* String... keyValues is a List of keys and values.
* The value always comes second and this is the one
* we want to compress.
*/
if (i % 2 == 0) {
String value = items.get(i);
try {
if ((2 * value.length()) > connPool.getConfiguration().getValueCompressionThreshold()) {
newItems.add(i, ZipUtils.compressStringToBase64String(value));
ctx.setMetadata("compression", true);
}
} catch (IOException e) {
Logger.warn(
"UNABLE to compress [" + value + "] for key [" + getStringKey() + "]; sending value uncompressed");
}
} else {
newItems.add(items.get(i));
}
}
return (String[]) newItems.toArray();
}
@Override
public String decompressValue(ConnectionContext ctx, String value) {
try {
if (ZipUtils.isCompressed(value)) {
ctx.setMetadata("decompression", true);
return ZipUtils.decompressFromBase64String(value);
}
} catch (IOException e) {
Logger.warn("Unable to decompress value [" + value + "]");
}
return value;
}
}
public TopologyView getTopologyView() {
return this.getConnPool();
}
public OperationResult moduleCommand(JedisGenericOperation handler) {
return connPool.executeWithFailover(handler);
}
@Override
public Long append(final String key, final String value) {
return d_append(key, value).getResult();
}
public OperationResult d_append(final String key, final String value) {
return connPool.executeWithFailover(new BaseKeyOperation(key, OpName.APPEND) {
@Override
public Long execute(Jedis client, ConnectionContext state) {
return client.append(key, value);
}
});
}
@Override
public Long decr(final String key) {
return d_decr(key).getResult();
}
public OperationResult d_decr(final String key) {
return connPool.executeWithFailover(new BaseKeyOperation(key, OpName.DECR) {
@Override
public Long execute(Jedis client, ConnectionContext state) {
return client.decr(key);
}
});
}
@Override
public Long decrBy(final String key, final long delta) {
return d_decrBy(key, delta).getResult();
}
public OperationResult d_decrBy(final String key, final Long delta) {
return connPool.executeWithFailover(new BaseKeyOperation(key, OpName.DECRBY) {
@Override
public Long execute(Jedis client, ConnectionContext state) {
return client.decrBy(key, delta);
}
});
}
@Override
public Long del(final String key) {
return d_del(key).getResult();
}
@Override
public Long unlink(String key) {
return d_unlink(key).getResult();
}
public OperationResult d_unlink(String key) {
return connPool.executeWithFailover(new BaseKeyOperation(key, OpName.UNLINK) {
@Override
public Long execute(Jedis client, ConnectionContext state) {
return client.unlink(key);
}
});
}
public OperationResult d_del(final String key) {
return connPool.executeWithFailover(new BaseKeyOperation(key, OpName.DEL) {
@Override
public Long execute(Jedis client, ConnectionContext state) {
return client.del(key);
}
});
}
public byte[] dump(final String key) {
return d_dump(key).getResult();
}
@Override
public String restore(String key, int ttl, byte[] serializedValue) {
throw new UnsupportedOperationException("not yet implemented");
}
@Override
public String restoreReplace(String key, int ttl, byte[] serializedValue) {
throw new UnsupportedOperationException("not yet implemented");
}
public OperationResult d_dump(final String key) {
return connPool.executeWithFailover(new BaseKeyOperation(key, OpName.DUMP) {
@Override
public byte[] execute(Jedis client, ConnectionContext state) {
return client.dump(key);
}
});
}
@Override
public Boolean exists(final String key) {
return d_exists(key).getResult();
}
public OperationResult d_exists(final String key) {
return connPool.executeWithFailover(new BaseKeyOperation(key, OpName.EXISTS) {
@Override
public Boolean execute(Jedis client, ConnectionContext state) {
return client.exists(key);
}
});
}
@Override
public Long expire(final String key, final int seconds) {
return d_expire(key, seconds).getResult();
}
public OperationResult d_expire(final String key, final int seconds) {
return connPool.executeWithFailover(new BaseKeyOperation(key, OpName.EXPIRE) {
@Override
public Long execute(Jedis client, ConnectionContext state) {
return client.expire(key, seconds);
}
});
}
@Override
public Long expireAt(final String key, final long unixTime) {
return d_expireAt(key, unixTime).getResult();
}
public OperationResult d_expireAt(final String key, final long unixTime) {
return connPool.executeWithFailover(new BaseKeyOperation(key, OpName.EXPIREAT) {
@Override
public Long execute(Jedis client, ConnectionContext state) {
return client.expireAt(key, unixTime);
}
});
}
@Override
public Object eval(String script, int keyCount, String... params) {
return d_eval(script, keyCount, params).getResult();
}
public OperationResult