package fr.xephi.authme.datasource; import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import org.bukkit.entity.Player; import fr.xephi.authme.AuthMe; import fr.xephi.authme.Utils; import fr.xephi.authme.cache.auth.PlayerAuth; import fr.xephi.authme.cache.auth.PlayerCache; public class CacheDataSource implements DataSource { private final ConcurrentHashMap cache = new ConcurrentHashMap<>(); private final ExecutorService exec; private final DataSource source; public CacheDataSource(AuthMe pl, DataSource src) { this.source = src; this.exec = Executors.newCachedThreadPool(); /* * We need to load all players in cache ... It will took more time to * load the server, but it will be much easier to check for an * isAuthAvailable ! */ exec.execute(new Runnable() { @Override public void run() { for (PlayerAuth auth : source.getAllAuths()) { cache.put(auth.getNickname().toLowerCase(), auth); } } }); } @Override public List autoPurgeDatabase(long until) { List cleared = source.autoPurgeDatabase(until); if (cleared.size() > 0) { for (PlayerAuth auth : cache.values()) { if (auth.getLastLogin() < until) { cache.remove(auth.getNickname()); } } } return cleared; } @Override public synchronized void close() { exec.shutdown(); source.close(); } @Override public int getAccountsRegistered() { return cache.size(); } @Override public List getAllAuths() { return new ArrayList<>(cache.values()); } @Override public synchronized List getAllAuthsByEmail(String email) { List result = new ArrayList<>(); for (Map.Entry stringPlayerAuthEntry : cache.entrySet()) { PlayerAuth p = stringPlayerAuthEntry.getValue(); if (p.getEmail().equals(email)) result.add(p.getNickname()); } return result; } @Override public synchronized List getAllAuthsByIp(String ip) { List result = new ArrayList<>(); for (Map.Entry stringPlayerAuthEntry : cache.entrySet()) { PlayerAuth p = stringPlayerAuthEntry.getValue(); if (p.getIp().equals(ip)) result.add(p.getNickname()); } return result; } @Override public synchronized List getAllAuthsByName(PlayerAuth auth) { List result = new ArrayList<>(); for (Map.Entry stringPlayerAuthEntry : cache.entrySet()) { PlayerAuth p = stringPlayerAuthEntry.getValue(); if (p.getIp().equals(auth.getIp())) result.add(p.getNickname()); } return result; } @Override public synchronized PlayerAuth getAuth(String user) { user = user.toLowerCase(); if (cache.containsKey(user)) { return cache.get(user); } return null; } @Override public int getIps(String ip) { int count = 0; for (Map.Entry p : cache.entrySet()) { if (p.getValue().getIp().equals(ip)) { count++; } } return count; } @Override public List getLoggedPlayers() { return new ArrayList<>(PlayerCache.getInstance().getCache().values()); } @Override public DataSourceType getType() { return source.getType(); } @Override public synchronized boolean isAuthAvailable(String user) { return cache.containsKey(user.toLowerCase()); } @Override public boolean isLogged(String user) { user = user.toLowerCase(); return PlayerCache.getInstance().getCache().containsKey(user); } @Override public synchronized void purgeBanned(final List banned) { exec.execute(new Runnable() { @Override public void run() { source.purgeBanned(banned); for (PlayerAuth auth : cache.values()) { if (banned.contains(auth.getNickname())) { cache.remove(auth.getNickname()); } } } }); } @Override public int purgeDatabase(long until) { int cleared = source.purgeDatabase(until); if (cleared > 0) { for (PlayerAuth auth : cache.values()) { if (auth.getLastLogin() < until) { cache.remove(auth.getNickname()); } } } return cleared; } @Override public void purgeLogged() { exec.execute(new Runnable() { @Override public void run() { source.purgeLogged(); } }); } @Override public void reload() { exec.execute(new Runnable() { @Override public void run() { cache.clear(); source.reload(); for (Player player : Utils.getOnlinePlayers()) { String user = player.getName().toLowerCase(); if (PlayerCache.getInstance().isAuthenticated(user)) { PlayerAuth auth = source.getAuth(user); cache.put(user, auth); } } } }); } @Override public synchronized boolean removeAuth(String username) { final String user = username.toLowerCase(); final PlayerAuth auth = cache.get(user); cache.remove(user); exec.execute(new Runnable() { @Override public void run() { if (!source.removeAuth(user)) { cache.put(user, auth); } } }); return true; } @Override public synchronized boolean saveAuth(final PlayerAuth auth) { cache.put(auth.getNickname(), auth); exec.execute(new Runnable() { @Override public void run() { if (!source.saveAuth(auth)) { cache.remove(auth.getNickname()); } } }); return true; } @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 synchronized boolean updateEmail(final PlayerAuth auth) { if (!cache.containsKey(auth.getNickname())) { return false; } PlayerAuth cachedAuth = cache.get(auth.getNickname()); final String oldEmail = cachedAuth.getEmail(); cachedAuth.setEmail(auth.getEmail()); exec.execute(new Runnable() { @Override public void run() { if (!source.updateEmail(auth)) { if (cache.containsKey(auth.getNickname())) { cache.get(auth.getNickname()).setEmail(oldEmail); } } } }); return true; } @Override public void updateName(final String oldone, final String newone) { if (cache.containsKey(oldone)) { cache.put(newone, cache.get(oldone)); cache.remove(oldone); } exec.execute(new Runnable() { @Override public void run() { source.updateName(oldone, newone); } }); } @Override public synchronized boolean updatePassword(final PlayerAuth auth) { if (!cache.containsKey(auth.getNickname())) { return false; } final String oldHash = cache.get(auth.getNickname()).getHash(); cache.get(auth.getNickname()).setHash(auth.getHash()); exec.execute(new Runnable() { @Override public void run() { if (!source.updatePassword(auth)) { if (cache.containsKey(auth.getNickname())) { cache.get(auth.getNickname()).setHash(oldHash); } } } }); return true; } @Override public boolean updateQuitLoc(final PlayerAuth auth) { if (!cache.containsKey(auth.getNickname())) { return false; } final PlayerAuth cachedAuth = cache.get(auth.getNickname()); final double oldX = cachedAuth.getQuitLocX(); final double oldY = cachedAuth.getQuitLocY(); final double oldZ = cachedAuth.getQuitLocZ(); final String oldWorld = cachedAuth.getWorld(); cachedAuth.setQuitLocX(auth.getQuitLocX()); cachedAuth.setQuitLocY(auth.getQuitLocY()); cachedAuth.setQuitLocZ(auth.getQuitLocZ()); cachedAuth.setWorld(auth.getWorld()); exec.execute(new Runnable() { @Override public void run() { if (!source.updateQuitLoc(auth)) { if (cache.containsKey(auth.getNickname())) { PlayerAuth cachedAuth = cache.get(auth.getNickname()); cachedAuth.setQuitLocX(oldX); cachedAuth.setQuitLocY(oldY); cachedAuth.setQuitLocZ(oldZ); cachedAuth.setWorld(oldWorld); } } } }); return true; } @Override public synchronized boolean updateSalt(final PlayerAuth auth) { if (!cache.containsKey(auth.getNickname())) { return false; } PlayerAuth cachedAuth = cache.get(auth.getNickname()); final String oldSalt = cachedAuth.getSalt(); cachedAuth.setSalt(auth.getSalt()); exec.execute(new Runnable() { @Override public void run() { if (!source.updateSalt(auth)) { if (cache.containsKey(auth.getNickname())) { cache.get(auth.getNickname()).setSalt(oldSalt); } } } }); return true; } @Override public boolean updateSession(final PlayerAuth auth) { if (!cache.containsKey(auth.getNickname())) { return false; } PlayerAuth cachedAuth = cache.get(auth.getNickname()); final String oldIp = cachedAuth.getIp(); final long oldLastLogin = cachedAuth.getLastLogin(); final String oldRealName = cachedAuth.getRealName(); cachedAuth.setIp(auth.getIp()); cachedAuth.setLastLogin(auth.getLastLogin()); cachedAuth.setRealName(auth.getRealName()); exec.execute(new Runnable() { @Override public void run() { if (!source.updateSession(auth)) { if (cache.containsKey(auth.getNickname())) { PlayerAuth cachedAuth = cache.get(auth.getNickname()); cachedAuth.setIp(oldIp); cachedAuth.setLastLogin(oldLastLogin); cachedAuth.setRealName(oldRealName); } } } }); return true; } }