LoginSystem/src/main/java/fr/xephi/authme/datasource/CacheDataSource.java
ljacqu 2ac89f5938 Apply minor changes to PurgeService
- Remove various imports / unused fields
- Make CacheDataSource call source for purging on DB
- Minor: SQLite - place creation of PreparedStatement outside of loop
- Make specific purge actions called from task package-private (clearer from the outside which methods can be called from the outside)
2016-06-16 21:04:12 +02:00

260 lines
7.2 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.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.ListeningExecutorService;
import com.google.common.util.concurrent.MoreExecutors;
import com.google.common.util.concurrent.ThreadFactoryBuilder;
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.Set;
import java.util.concurrent.Callable;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
public class CacheDataSource implements DataSource {
private final DataSource source;
private final LoadingCache<String, Optional<PlayerAuth>> cachedAuths;
private final ListeningExecutorService executorService;
/**
* Constructor for CacheDataSource.
*
* @param src DataSource
*/
public CacheDataSource(DataSource src) {
source = src;
executorService = MoreExecutors.listeningDecorator(
Executors.newCachedThreadPool(new ThreadFactoryBuilder()
.setDaemon(true)
.setNameFormat("AuthMe-CacheLoader")
.build())
);
cachedAuths = CacheBuilder.newBuilder()
.refreshAfterWrite(5, TimeUnit.MINUTES)
.expireAfterAccess(15, TimeUnit.MINUTES)
.build(new CacheLoader<String, Optional<PlayerAuth>>() {
@Override
public Optional<PlayerAuth> load(String key) {
return Optional.fromNullable(source.getAuth(key));
}
@Override
public ListenableFuture<Optional<PlayerAuth>> reload(final String key, Optional<PlayerAuth> oldValue) {
return executorService.submit(new Callable<Optional<PlayerAuth>>() {
@Override
public Optional<PlayerAuth> call() {
ConsoleLogger.debug("REFRESH " + key);
return load(key);
}
});
}
});
}
public LoadingCache<String, Optional<PlayerAuth>> getCachedAuths() {
return cachedAuths;
}
@Override
public void reload() {
source.reload();
}
@Override
public 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);
}
@Override
public PlayerAuth getAuth(String user) {
user = user.toLowerCase();
return cachedAuths.getUnchecked(user).orNull();
}
@Override
public boolean saveAuth(PlayerAuth auth) {
boolean result = source.saveAuth(auth);
if (result) {
cachedAuths.refresh(auth.getNickname());
}
return result;
}
@Override
public 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 Set<String> getRecordsToPurge(long until) {
return source.getRecordsToPurge(until);
}
@Override
public void purgeRecords(Set<String> toPurge) {
source.purgeRecords(toPurge);
for (String name : toPurge) {
cachedAuths.invalidate(name);
}
}
@Override
public boolean removeAuth(String name) {
name = name.toLowerCase();
boolean result = source.removeAuth(name);
if (result) {
cachedAuths.invalidate(name);
}
return result;
}
@Override
public void close() {
source.close();
cachedAuths.invalidateAll();
executorService.shutdown();
try {
executorService.awaitTermination(5, TimeUnit.SECONDS);
} catch (InterruptedException e) {
ConsoleLogger.writeStackTrace(e);
}
}
@Override
public boolean updateEmail(final PlayerAuth auth) {
boolean result = source.updateEmail(auth);
if (result) {
cachedAuths.refresh(auth.getNickname());
}
return result;
}
@Override
public List<String> getAllAuthsByIp(final String ip) {
return source.getAllAuthsByIp(ip);
}
@Override
public int countAuthsByEmail(final String email) {
return source.countAuthsByEmail(email);
}
@Override
public void purgeBanned(final Set<String> banned) {
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) {
source.setLogged(user.toLowerCase());
}
@Override
public void setUnlogged(final String user) {
source.setUnlogged(user.toLowerCase());
}
@Override
public void purgeLogged() {
source.purgeLogged();
cachedAuths.invalidateAll();
}
@Override
public int getAccountsRegistered() {
return source.getAccountsRegistered();
}
@Override
public boolean updateRealName(String user, String realName) {
boolean result = source.updateRealName(user, realName);
if (result) {
cachedAuths.refresh(user);
}
return result;
}
@Override
public boolean updateIp(String user, String ip) {
boolean result = source.updateIp(user, ip);
if (result) {
cachedAuths.refresh(user);
}
return result;
}
@Override
public List<PlayerAuth> getAllAuths() {
return source.getAllAuths();
}
@Override
public List<PlayerAuth> getLoggedPlayers() {
return new ArrayList<>(PlayerCache.getInstance().getCache().values());
}
}