LoginSystem/src/main/java/fr/xephi/authme/datasource/CacheDataSource.java
2016-02-05 23:27:34 +07:00

292 lines
8.0 KiB
Java

package fr.xephi.authme.datasource;
import com.google.common.base.Optional;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import com.google.common.cache.RemovalListener;
import com.google.common.cache.RemovalNotification;
import fr.xephi.authme.ConsoleLogger;
import fr.xephi.authme.cache.auth.PlayerAuth;
import fr.xephi.authme.cache.auth.PlayerCache;
import fr.xephi.authme.security.crypts.HashedPassword;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
/**
*/
public class CacheDataSource implements DataSource {
private final DataSource source;
private final ExecutorService exec;
private final LoadingCache<String, Optional<PlayerAuth>> cachedAuths;
/**
* Constructor for CacheDataSource.
*
* @param src DataSource
*/
public CacheDataSource(DataSource src) {
this.source = src;
this.exec = Executors.newCachedThreadPool();
this.cachedAuths = CacheBuilder.newBuilder()
.expireAfterWrite(8, TimeUnit.MINUTES)
.removalListener(new RemovalListener<String, Optional<PlayerAuth>>() {
@Override
public void onRemoval(RemovalNotification<String, Optional<PlayerAuth>> removalNotification) {
String name = removalNotification.getKey();
if (PlayerCache.getInstance().isAuthenticated(name)) {
cachedAuths.getUnchecked(name);
}
}
})
.build(
new CacheLoader<String, Optional<PlayerAuth>>() {
public Optional<PlayerAuth> load(String key) {
return Optional.fromNullable(source.getAuth(key));
}
});
}
@Override
public synchronized boolean isAuthAvailable(String user) {
return getAuth(user) != null;
}
@Override
public HashedPassword getPassword(String user) {
user = user.toLowerCase();
Optional<PlayerAuth> pAuthOpt = cachedAuths.getIfPresent(user);
if (pAuthOpt != null && pAuthOpt.isPresent()) {
return pAuthOpt.get().getPassword();
}
return source.getPassword(user);
}
/**
* Method getAuth.
*
* @param user String
*
* @return PlayerAuth
*
* @see fr.xephi.authme.datasource.DataSource#getAuth(String)
*/
@Override
public synchronized PlayerAuth getAuth(String user) {
user = user.toLowerCase();
return cachedAuths.getUnchecked(user).orNull();
}
@Override
public synchronized boolean saveAuth(PlayerAuth auth) {
boolean result = source.saveAuth(auth);
if (result) {
cachedAuths.refresh(auth.getNickname());
}
return result;
}
@Override
public synchronized boolean updatePassword(PlayerAuth auth) {
boolean result = source.updatePassword(auth);
if (result) {
cachedAuths.refresh(auth.getNickname());
}
return result;
}
@Override
public boolean updatePassword(String user, HashedPassword password) {
user = user.toLowerCase();
boolean result = source.updatePassword(user, password);
if (result) {
cachedAuths.refresh(user);
}
return result;
}
@Override
public boolean updateSession(PlayerAuth auth) {
boolean result = source.updateSession(auth);
if (result) {
cachedAuths.refresh(auth.getNickname());
}
return result;
}
@Override
public boolean updateQuitLoc(final PlayerAuth auth) {
boolean result = source.updateQuitLoc(auth);
if (result) {
cachedAuths.refresh(auth.getNickname());
}
return result;
}
@Override
public int getIps(String ip) {
return source.getIps(ip);
}
@Override
public int purgeDatabase(long until) {
int cleared = source.purgeDatabase(until);
if (cleared > 0) {
for (Optional<PlayerAuth> auth : cachedAuths.asMap().values()) {
if (auth.isPresent() && auth.get().getLastLogin() < until) {
cachedAuths.invalidate(auth.get().getNickname());
}
}
}
return cleared;
}
@Override
public List<String> autoPurgeDatabase(long until) {
List<String> cleared = source.autoPurgeDatabase(until);
for (String name : cleared) {
cachedAuths.invalidate(name);
}
return cleared;
}
@Override
public synchronized boolean removeAuth(String name) {
name = name.toLowerCase();
boolean result = source.removeAuth(name);
if (result) {
cachedAuths.invalidate(name);
}
return result;
}
@Override
public synchronized void close() {
try {
exec.shutdown();
exec.awaitTermination(8, TimeUnit.SECONDS);
} catch (InterruptedException e) {
ConsoleLogger.writeStackTrace("Error while closing CacheDataSource.", e);
}
source.close();
}
@Override
public void reload() { // unused method
exec.execute(new Runnable() {
@Override
public void run() {
source.reload();
cachedAuths.invalidateAll();
}
});
}
@Override
public synchronized boolean updateEmail(final PlayerAuth auth) {
boolean result = source.updateEmail(auth);
if (result) {
cachedAuths.refresh(auth.getNickname());
}
return result;
}
@Override
public synchronized List<String> getAllAuthsByName(PlayerAuth auth) {
return source.getAllAuthsByName(auth);
}
@Override
public synchronized List<String> getAllAuthsByIp(final String ip) {
return source.getAllAuthsByIp(ip);
}
@Override
public synchronized List<String> getAllAuthsByEmail(final String email) {
return source.getAllAuthsByEmail(email);
}
@Override
public synchronized void purgeBanned(final List<String> banned) {
exec.execute(new Runnable() {
@Override
public void run() {
source.purgeBanned(banned);
cachedAuths.invalidateAll(banned);
}
});
}
@Override
public DataSourceType getType() {
return source.getType();
}
@Override
public boolean isLogged(String user) {
return PlayerCache.getInstance().isAuthenticated(user);
}
@Override
public void setLogged(final String user) {
exec.execute(new Runnable() {
@Override
public void run() {
source.setLogged(user.toLowerCase());
}
});
}
@Override
public void setUnlogged(final String user) {
exec.execute(new Runnable() {
@Override
public void run() {
source.setUnlogged(user.toLowerCase());
}
});
}
@Override
public void purgeLogged() {
exec.execute(new Runnable() {
@Override
public void run() {
source.purgeLogged();
cachedAuths.invalidateAll();
}
});
}
@Override
public int getAccountsRegistered() {
return source.getAccountsRegistered();
}
@Override
public void updateName(final String oldOne, final String newOne) {
exec.execute(new Runnable() {
@Override
public void run() {
source.updateName(oldOne, newOne);
cachedAuths.invalidate(oldOne);
}
});
}
@Override
public List<PlayerAuth> getAllAuths() {
return source.getAllAuths();
}
@Override
public List<PlayerAuth> getLoggedPlayers() {
return new ArrayList<>(PlayerCache.getInstance().getCache().values());
}
}