Bug fixes and added redis sentinel supportability changes.
parent
c41cfedd77
commit
8aa5359453
|
@ -17,9 +17,9 @@ public class DataCacheFactory {
|
||||||
|
|
||||||
private static final Log LOGGER = LogFactory.getLog(DataCacheFactory.class);
|
private static final Log LOGGER = LogFactory.getLog(DataCacheFactory.class);
|
||||||
|
|
||||||
private final long sessionExpiryTime;
|
private final int sessionExpiryTime;
|
||||||
|
|
||||||
public DataCacheFactory(long sessionExpiryTime) {
|
public DataCacheFactory(int sessionExpiryTime) {
|
||||||
this.sessionExpiryTime = sessionExpiryTime;
|
this.sessionExpiryTime = sessionExpiryTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,6 +2,7 @@ package tomcat.request.session.data.cache.impl;
|
||||||
|
|
||||||
import org.apache.commons.logging.Log;
|
import org.apache.commons.logging.Log;
|
||||||
import org.apache.commons.logging.LogFactory;
|
import org.apache.commons.logging.LogFactory;
|
||||||
|
import tomcat.request.session.data.cache.DataCache;
|
||||||
import tomcat.request.session.data.cache.impl.redis.RedisCache;
|
import tomcat.request.session.data.cache.impl.redis.RedisCache;
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
|
@ -14,30 +15,42 @@ import java.util.concurrent.ConcurrentHashMap;
|
||||||
public class StandardDataCache extends RedisCache {
|
public class StandardDataCache extends RedisCache {
|
||||||
|
|
||||||
private Date lastSessionJobRun;
|
private Date lastSessionJobRun;
|
||||||
|
private boolean triggerRedisSync;
|
||||||
|
|
||||||
|
private final int sessionExpiryTime;
|
||||||
private final Map<String, SessionData> sessionData;
|
private final Map<String, SessionData> sessionData;
|
||||||
|
|
||||||
private final long sessionExpiryTime;
|
public StandardDataCache(Properties properties, int sessionExpiryTime) {
|
||||||
|
|
||||||
public StandardDataCache(Properties properties, long sessionExpiryTime) {
|
|
||||||
super(properties);
|
super(properties);
|
||||||
this.sessionExpiryTime = (sessionExpiryTime + 60) / 60;
|
this.sessionExpiryTime = sessionExpiryTime;
|
||||||
this.lastSessionJobRun = new Date();
|
|
||||||
this.sessionData = new ConcurrentHashMap<>();
|
this.sessionData = new ConcurrentHashMap<>();
|
||||||
|
this.lastSessionJobRun = new Date();
|
||||||
|
this.triggerRedisSync = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** {@inheritDoc} */
|
/** {@inheritDoc} */
|
||||||
@Override
|
@Override
|
||||||
public byte[] set(String key, byte[] value) {
|
public byte[] set(String key, byte[] value) {
|
||||||
triggerSessionExpiry();
|
|
||||||
this.sessionData.put(key, new SessionData(value));
|
this.sessionData.put(key, new SessionData(value));
|
||||||
return super.set(key, value);
|
try {
|
||||||
|
return super.set(key, value);
|
||||||
|
} catch (RuntimeException ex) {
|
||||||
|
this.triggerRedisSync = true;
|
||||||
|
}
|
||||||
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** {@inheritDoc} */
|
/** {@inheritDoc} */
|
||||||
@Override
|
@Override
|
||||||
public Long setnx(String key, byte[] value) {
|
public Long setnx(String key, byte[] value) {
|
||||||
triggerSessionExpiry();
|
Long retValue;
|
||||||
Long retValue = super.setnx(key, value);
|
try {
|
||||||
|
retValue = super.setnx(key, value);
|
||||||
|
} catch (RuntimeException ex) {
|
||||||
|
retValue = this.sessionData.containsKey(key) ? 0L : 1L;
|
||||||
|
this.triggerRedisSync = true;
|
||||||
|
}
|
||||||
|
|
||||||
if (retValue == 1L) {
|
if (retValue == 1L) {
|
||||||
this.sessionData.put(key, new SessionData(value));
|
this.sessionData.put(key, new SessionData(value));
|
||||||
}
|
}
|
||||||
|
@ -47,24 +60,39 @@ public class StandardDataCache extends RedisCache {
|
||||||
/** {@inheritDoc} */
|
/** {@inheritDoc} */
|
||||||
@Override
|
@Override
|
||||||
public Long expire(String key, int seconds) {
|
public Long expire(String key, int seconds) {
|
||||||
return super.expire(key, seconds);
|
try {
|
||||||
|
return super.expire(key, seconds);
|
||||||
|
} catch (RuntimeException ex) {
|
||||||
|
this.triggerRedisSync = true;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** {@inheritDoc} */
|
/** {@inheritDoc} */
|
||||||
@Override
|
@Override
|
||||||
public byte[] get(String key) {
|
public byte[] get(String key) {
|
||||||
triggerSessionExpiry();
|
handleSessionData();
|
||||||
if (this.sessionData.containsKey(key)) {
|
if (this.sessionData.containsKey(key)) {
|
||||||
return this.sessionData.get(key).getValue();
|
return this.sessionData.get(key).getValue();
|
||||||
}
|
}
|
||||||
return super.get(key);
|
try {
|
||||||
|
return super.get(key);
|
||||||
|
} catch (RuntimeException ex) {
|
||||||
|
this.triggerRedisSync = true;
|
||||||
|
throw ex;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** {@inheritDoc} */
|
/** {@inheritDoc} */
|
||||||
@Override
|
@Override
|
||||||
public Long delete(String key) {
|
public Long delete(String key) {
|
||||||
this.sessionData.remove(key);
|
Object value = this.sessionData.remove(key);
|
||||||
return super.delete(key);
|
try {
|
||||||
|
return super.delete(key);
|
||||||
|
} catch (RuntimeException ex) {
|
||||||
|
this.triggerRedisSync = true;
|
||||||
|
}
|
||||||
|
return (value == null) ? 0L : 1L;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Session data. */
|
/** Session data. */
|
||||||
|
@ -91,15 +119,54 @@ public class StandardDataCache extends RedisCache {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** To trigger session expiry thread. */
|
/** To handle session data. */
|
||||||
private void triggerSessionExpiry() {
|
private synchronized void handleSessionData() {
|
||||||
|
// redis sync
|
||||||
|
if (this.triggerRedisSync) {
|
||||||
|
new SessionDataSyncThread(this, this.sessionData, this.sessionExpiryTime);
|
||||||
|
this.triggerRedisSync = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// session expiry
|
||||||
long diff = new Date().getTime() - this.lastSessionJobRun.getTime();
|
long diff = new Date().getTime() - this.lastSessionJobRun.getTime();
|
||||||
long diffMinutes = diff / (60 * 1000) % 60;
|
long diffMinutes = diff / (60 * 1000) % 60;
|
||||||
|
|
||||||
if (diffMinutes > 0L) {
|
if (diffMinutes > 0L) {
|
||||||
synchronized (this) {
|
new SessionDataExpiryThread(this.sessionData, this.sessionExpiryTime);
|
||||||
new SessionDataExpiryThread(this.sessionData, this.sessionExpiryTime);
|
this.lastSessionJobRun = new Date();
|
||||||
this.lastSessionJobRun = new Date();
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Session data redis sync thread. */
|
||||||
|
private class SessionDataSyncThread implements Runnable {
|
||||||
|
|
||||||
|
private final Log LOGGER = LogFactory.getLog(SessionDataSyncThread.class);
|
||||||
|
|
||||||
|
private final DataCache dataCache;
|
||||||
|
private final int sessionExpiryTime;
|
||||||
|
private final Map<String, SessionData> sessionData;
|
||||||
|
|
||||||
|
SessionDataSyncThread(DataCache dataCache, Map<String, SessionData> sessionData, int sessionExpiryTime) {
|
||||||
|
this.dataCache = dataCache;
|
||||||
|
this.sessionData = sessionData;
|
||||||
|
this.sessionExpiryTime = sessionExpiryTime;
|
||||||
|
new Thread(this).start();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** {@inheritDoc} */
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
try {
|
||||||
|
for (String key : this.sessionData.keySet()) {
|
||||||
|
SessionData data = this.sessionData.get(key);
|
||||||
|
if (data == null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
this.dataCache.set(key, data.getValue());
|
||||||
|
this.dataCache.expire(key, this.sessionExpiryTime);
|
||||||
|
}
|
||||||
|
} catch (Exception ex) {
|
||||||
|
LOGGER.error("Error processing session data expiry thread", ex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -109,12 +176,12 @@ public class StandardDataCache extends RedisCache {
|
||||||
|
|
||||||
private final Log LOGGER = LogFactory.getLog(SessionDataExpiryThread.class);
|
private final Log LOGGER = LogFactory.getLog(SessionDataExpiryThread.class);
|
||||||
|
|
||||||
private final long sessionExpiryTime;
|
private final int sessionExpiryTime;
|
||||||
private final Map<String, SessionData> sessionData;
|
private final Map<String, SessionData> sessionData;
|
||||||
|
|
||||||
SessionDataExpiryThread(Map<String, SessionData> sessionData, long sessionExpiryTime) {
|
SessionDataExpiryThread(Map<String, SessionData> sessionData, int sessionExpiryTime) {
|
||||||
this.sessionData = sessionData;
|
this.sessionData = sessionData;
|
||||||
this.sessionExpiryTime = sessionExpiryTime;
|
this.sessionExpiryTime = (sessionExpiryTime + 60) / 60;
|
||||||
new Thread(this).start();
|
new Thread(this).start();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue