package ddth.dasp.framework.cache.redis;
import java.io.IOException;
import ddth.dasp.common.redis.IRedisClient;
import ddth.dasp.common.redis.IRedisClientFactory;
import ddth.dasp.common.redis.PoolConfig;
import ddth.dasp.framework.cache.AbstractCache;
import ddth.dasp.framework.cache.CacheEntry;
import ddth.dasp.framework.cache.ICache;
import ddth.dasp.framework.utils.SerializeUtils;
/**
* <a href="http://www.hazelcast.com/">Hazelcast</a> implementation of
* {@link ICache}.
*
* @author NBThanh <btnguyen2k@gmail.com>
* @version 0.1.0
*/
public class RedisCache extends AbstractCache implements ICache {
private RedisCacheManager redisCacheManager;
private String redisHost = "localhost", redisUsername, redisPassword;
private int redisPort = IRedisClient.DEFAULT_REDIS_PORT;
private PoolConfig poolConfig;
private long timeToLiveSeconds = -1;
public RedisCache(RedisCacheManager redisCacheManager) {
this.redisCacheManager = redisCacheManager;
}
public RedisCache(RedisCacheManager redisCacheManager, String name) {
super(name);
this.redisCacheManager = redisCacheManager;
}
public RedisCache(RedisCacheManager redisCacheManager, String name, long capacity) {
super(name, capacity);
this.redisCacheManager = redisCacheManager;
}
public RedisCache(RedisCacheManager redisCacheManager, String name, long capacity,
long expireAfterWrite, long expireAfterAccess) {
super(name, capacity, expireAfterWrite, expireAfterAccess);
this.redisCacheManager = redisCacheManager;
}
protected IRedisClientFactory getRedisClientFactory() {
return redisCacheManager.getRedisClientFactory();
}
public String getRedisHost() {
return redisHost;
}
public RedisCache setRedisHost(String redisHost) {
this.redisHost = redisHost;
return this;
}
public String getRedisUsername() {
return redisUsername;
}
public RedisCache setRedisUsername(String redisUsername) {
this.redisUsername = redisUsername;
return this;
}
public String getRedisPassword() {
return redisPassword;
}
public RedisCache setRedisPassword(String redisPassword) {
this.redisPassword = redisPassword;
return this;
}
public int getRedisPort() {
return redisPort;
}
public RedisCache setRedisPort(int redisPort) {
this.redisPort = redisPort;
return this;
}
public PoolConfig getPoolConfig() {
return poolConfig;
}
public RedisCache setPoolConfig(PoolConfig poolConfig) {
this.poolConfig = poolConfig;
return this;
}
/**
* Serializes an object to byte array.
*
* @param obj
* @return
* @throws IOException
*/
protected byte[] serializeObject(Object obj) throws IOException {
return SerializeUtils.serialize(obj);
}
/**
* Deserializes object from byte array.
*
* @param byteArr
* @return
* @throws IOException
* @throws ClassNotFoundException
*/
protected Object deserializeObject(byte[] byteArr) throws IOException, ClassNotFoundException {
return SerializeUtils.deserialize(byteArr);
}
/**
* Generic version of {@link #deserializeObject(byte[])}.
*
* @param byteArr
* @param clazz
* @return
* @throws IOException
* @throws ClassNotFoundException
*/
protected <T> T deserializeObject(byte[] byteArr, Class<T> clazz) throws IOException,
ClassNotFoundException {
return SerializeUtils.deserialize(byteArr, clazz);
}
/**
* {@inheritDoc}
*/
@Override
public void init() {
super.init();
long expireAfterWrite = getExpireAfterWrite();
long expireAfterAccess = getExpireAfterAccess();
if (expireAfterAccess > 0 || expireAfterWrite > 0) {
timeToLiveSeconds = expireAfterAccess > 0 ? expireAfterAccess : expireAfterWrite;
} else {
timeToLiveSeconds = -1;
}
}
/**
* {@inheritDoc}
*/
@Override
public void destroy() {
// EMPTY
}
private IRedisClient getRedisClient() {
IRedisClientFactory redisClientFactory = getRedisClientFactory();
return redisClientFactory != null ? redisClientFactory.getRedisClient(redisHost, redisPort,
redisUsername, redisPassword, poolConfig) : null;
}
private void returnRedisClient(IRedisClient redisClient) {
if (redisClient != null) {
getRedisClientFactory().returnRedisClient(redisClient);
}
}
/**
* {@inheritDoc}
*/
@Override
public long getSize() {
IRedisClient redisClient = getRedisClient();
try {
return redisClient != null ? redisClient.hashSize(getName()) : -1;
} finally {
returnRedisClient(redisClient);
}
}
/**
* {@inheritDoc}
*/
@Override
public void set(String key, Object entry) {
if (entry instanceof CacheEntry) {
CacheEntry ce = (CacheEntry) entry;
set(key, ce, ce.getExpireAfterWrite(), ce.getExpireAfterAccess());
} else {
set(key, entry, getExpireAfterWrite(), getExpireAfterAccess());
}
}
/**
* {@inheritDoc}
*/
public void set(String key, Object entry, long expireAfterWrite, long expireAfterAccess) {
IRedisClient redisClient = getRedisClient();
if (redisClient != null) {
try {
long ttl = expireAfterAccess > 0 ? expireAfterAccess
: (expireAfterWrite > 0 ? expireAfterWrite : timeToLiveSeconds);
redisClient.hashSet(getName(), key, serializeObject(entry), (int) ttl);
} catch (Exception e) {
throw new RuntimeException(e);
} finally {
returnRedisClient(redisClient);
}
}
}
/**
* {@inheritDoc}
*/
@Override
protected Object internalGet(String key) {
IRedisClient redisClient = getRedisClient();
if (redisClient != null) {
try {
byte[] obj = redisClient.hashGetAsBinary(getName(), key);
if (obj != null) {
long expireAfterAccess = getExpireAfterAccess();
if (expireAfterAccess > 0) {
redisClient.expire(getName(), (int) expireAfterAccess);
}
return deserializeObject(obj);
} else {
return null;
}
} catch (Exception e) {
throw new RuntimeException(e);
} finally {
returnRedisClient(redisClient);
}
} else {
return null;
}
}
/**
* {@inheritDoc}
*/
@Override
public void delete(String key) {
IRedisClient redisClient = getRedisClient();
if (redisClient != null) {
try {
redisClient.hashDelete(getName(), key);
} finally {
returnRedisClient(redisClient);
}
}
}
/**
* {@inheritDoc}
*/
@Override
public void deleteAll() {
IRedisClient redisClient = getRedisClient();
if (redisClient != null) {
try {
redisClient.delete(getName());
} finally {
returnRedisClient(redisClient);
}
}
}
/**
* {@inheritDoc}
*/
@Override
public boolean exists(String key) {
IRedisClient redisClient = getRedisClient();
if (redisClient != null) {
try {
return redisClient.hashGet(getName(), key) != null;
} finally {
returnRedisClient(redisClient);
}
}
return false;
}
}