mirror of
https://github.com/proxiodev/RedisBungee.git
synced 2024-11-23 04:28:01 +00:00
Enhance the UUIDTranslator and add an option to increase performance.
This commit is contained in:
parent
92971fce96
commit
a908e313d4
@ -87,7 +87,7 @@ public class RedisBungeeAPI {
|
|||||||
return Collections2.transform(getPlayersOnline(), new Function<UUID, String>() {
|
return Collections2.transform(getPlayersOnline(), new Function<UUID, String>() {
|
||||||
@Override
|
@Override
|
||||||
public String apply(UUID uuid) {
|
public String apply(UUID uuid) {
|
||||||
return getNameFromUuid(uuid);
|
return getNameFromUuid(uuid, false);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -205,24 +205,66 @@ public class RedisBungeeAPI {
|
|||||||
* <p>
|
* <p>
|
||||||
* For the common use case of translating a list of UUIDs into names, use {@link #getHumanPlayersOnline()}
|
* For the common use case of translating a list of UUIDs into names, use {@link #getHumanPlayersOnline()}
|
||||||
* as the efficiency of that function is slightly greater as the names are calculated lazily.
|
* as the efficiency of that function is slightly greater as the names are calculated lazily.
|
||||||
|
* <p>
|
||||||
|
* If performance is a concern, use {@link #getNameFromUuid(java.util.UUID, boolean)} as this allows you to disable Mojang lookups.
|
||||||
*
|
*
|
||||||
* @param uuid the UUID to fetch the name for
|
* @param uuid the UUID to fetch the name for
|
||||||
* @return the name for the UUID
|
* @return the name for the UUID
|
||||||
* @since 0.3
|
* @since 0.3
|
||||||
*/
|
*/
|
||||||
public final String getNameFromUuid(@NonNull UUID uuid) {
|
public final String getNameFromUuid(@NonNull UUID uuid) {
|
||||||
return plugin.getUuidTranslator().getNameFromUuid(uuid);
|
return getNameFromUuid(uuid, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fetch a name from the specified UUID. UUIDs are cached locally and in Redis. This function can fall back to Mojang
|
||||||
|
* as a last resort if {@code expensiveLookups} is true, so calls <strong>may</strong> be blocking.
|
||||||
|
* <p>
|
||||||
|
* For the common use case of translating the list of online players into names, use {@link #getHumanPlayersOnline()}
|
||||||
|
* as the efficiency of that function is slightly greater as the names are calculated lazily.
|
||||||
|
* <p>
|
||||||
|
* If performance is a concern, set {@code expensiveLookups} to false as this will disable lookups via Mojang.
|
||||||
|
*
|
||||||
|
* @param uuid the UUID to fetch the name for
|
||||||
|
* @param expensiveLookups whether or not to perform potentially expensive lookups
|
||||||
|
* @return the name for the UUID
|
||||||
|
* @since 0.3.2
|
||||||
|
*/
|
||||||
|
public final String getNameFromUuid(@NonNull UUID uuid, boolean expensiveLookups) {
|
||||||
|
return plugin.getUuidTranslator().getNameFromUuid(uuid, expensiveLookups);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Fetch a UUID from the specified name. Names are cached locally and in Redis. This function falls back to Mojang
|
* Fetch a UUID from the specified name. Names are cached locally and in Redis. This function falls back to Mojang
|
||||||
* as a last resort, so calls <strong>may</strong> be blocking.
|
* as a last resort, so calls <strong>may</strong> be blocking.
|
||||||
|
* <p>
|
||||||
|
* If performance is a concern, see {@link #getUuidFromName(String, boolean)}, which disables the following functions:
|
||||||
|
* <ul>
|
||||||
|
* <li>Searching local entries case-insensitively</li>
|
||||||
|
* <li>Searching Mojang</li>
|
||||||
|
* </ul>
|
||||||
*
|
*
|
||||||
* @param name the UUID to fetch the name for
|
* @param name the UUID to fetch the name for
|
||||||
* @return the UUID for the name
|
* @return the UUID for the name
|
||||||
* @since 0.3
|
* @since 0.3
|
||||||
*/
|
*/
|
||||||
public final UUID getUuidFromName(@NonNull String name) {
|
public final UUID getUuidFromName(@NonNull String name) {
|
||||||
return plugin.getUuidTranslator().getTranslatedUuid(name);
|
return getUuidFromName(name, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fetch a UUID from the specified name. Names are cached locally and in Redis. This function falls back to Mojang
|
||||||
|
* as a last resort if {@code expensiveLookups} is true, so calls <strong>may</strong> be blocking.
|
||||||
|
* <p>
|
||||||
|
* If performance is a concern, set {@code expensiveLookups} to false to disable searching Mojang and searching for usernames
|
||||||
|
* case-insensitively.
|
||||||
|
*
|
||||||
|
* @param name the UUID to fetch the name for
|
||||||
|
* @param expensiveLookups whether or not to perform potentially expensive lookups
|
||||||
|
* @return the UUID for the name
|
||||||
|
* @since 0.3.2
|
||||||
|
*/
|
||||||
|
public final UUID getUuidFromName(@NonNull String name, boolean expensiveLookups) {
|
||||||
|
return plugin.getUuidTranslator().getTranslatedUuid(name, expensiveLookups);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -20,24 +20,36 @@ import redis.clients.jedis.exceptions.JedisException;
|
|||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
import java.util.concurrent.locks.ReadWriteLock;
|
||||||
|
import java.util.concurrent.locks.ReentrantReadWriteLock;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
@RequiredArgsConstructor
|
@RequiredArgsConstructor
|
||||||
public class UUIDTranslator {
|
public class UUIDTranslator {
|
||||||
private final RedisBungee plugin;
|
private final RedisBungee plugin;
|
||||||
private BiMap<String, UUID> uuidMap = Maps.synchronizedBiMap(HashBiMap.<String, UUID>create());
|
private final BiMap<String, UUID> uuidMap = HashBiMap.create();
|
||||||
|
private final ReadWriteLock lock = new ReentrantReadWriteLock();
|
||||||
public static final Pattern UUID_PATTERN = Pattern.compile("[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{12}");
|
public static final Pattern UUID_PATTERN = Pattern.compile("[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{12}");
|
||||||
public static final Pattern MOJANGIAN_UUID_PATTERN = Pattern.compile("[a-fA-F0-9]{32}");
|
public static final Pattern MOJANGIAN_UUID_PATTERN = Pattern.compile("[a-fA-F0-9]{32}");
|
||||||
|
|
||||||
public UUID getTranslatedUuid(@NonNull String player) {
|
public UUID getTranslatedUuid(@NonNull String player, boolean expensiveLookups) {
|
||||||
if (ProxyServer.getInstance().getPlayer(player) != null)
|
if (ProxyServer.getInstance().getPlayer(player) != null)
|
||||||
return ProxyServer.getInstance().getPlayer(player).getUniqueId();
|
return ProxyServer.getInstance().getPlayer(player).getUniqueId();
|
||||||
|
|
||||||
UUID uuid = uuidMap.get(player);
|
UUID uuid;
|
||||||
|
|
||||||
|
// Check if it exists in the map
|
||||||
|
lock.readLock().lock();
|
||||||
|
try {
|
||||||
|
uuid = uuidMap.get(player);
|
||||||
if (uuid != null)
|
if (uuid != null)
|
||||||
return uuid;
|
return uuid;
|
||||||
|
} finally {
|
||||||
|
lock.readLock().unlock();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if we can exit early
|
||||||
if (UUID_PATTERN.matcher(player).find()) {
|
if (UUID_PATTERN.matcher(player).find()) {
|
||||||
return UUID.fromString(player);
|
return UUID.fromString(player);
|
||||||
}
|
}
|
||||||
@ -53,7 +65,21 @@ public class UUIDTranslator {
|
|||||||
return uuid;
|
return uuid;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Okay, it wasn't locally cached. Let's try Redis.
|
// We could not exit early. Look for the name, ignoring case.
|
||||||
|
if (expensiveLookups) {
|
||||||
|
lock.readLock().lock();
|
||||||
|
try {
|
||||||
|
for (Map.Entry<String, UUID> entry : uuidMap.entrySet()) {
|
||||||
|
if (entry.getKey().equalsIgnoreCase(player)) {
|
||||||
|
return entry.getValue();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
lock.readLock().unlock();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Okay, it wasn't locally cached and the expensive search didn't help us. Let's try Redis.
|
||||||
Jedis jedis = plugin.getPool().getResource();
|
Jedis jedis = plugin.getPool().getResource();
|
||||||
try {
|
try {
|
||||||
try {
|
try {
|
||||||
@ -62,11 +88,19 @@ public class UUIDTranslator {
|
|||||||
// This is it!
|
// This is it!
|
||||||
uuid = UUID.fromString(stored);
|
uuid = UUID.fromString(stored);
|
||||||
storeInfo(player, uuid, jedis);
|
storeInfo(player, uuid, jedis);
|
||||||
|
lock.writeLock().lock();
|
||||||
|
try {
|
||||||
uuidMap.put(player, uuid);
|
uuidMap.put(player, uuid);
|
||||||
|
} finally {
|
||||||
|
lock.writeLock().unlock();
|
||||||
|
}
|
||||||
return uuid;
|
return uuid;
|
||||||
}
|
}
|
||||||
|
|
||||||
// That didn't work. Let's ask Mojang.
|
// That didn't work. Let's ask Mojang.
|
||||||
|
if (!expensiveLookups)
|
||||||
|
return null;
|
||||||
|
|
||||||
Map<String, UUID> uuidMap1;
|
Map<String, UUID> uuidMap1;
|
||||||
try {
|
try {
|
||||||
uuidMap1 = new UUIDFetcher(Collections.singletonList(player)).call();
|
uuidMap1 = new UUIDFetcher(Collections.singletonList(player)).call();
|
||||||
@ -76,8 +110,12 @@ public class UUIDTranslator {
|
|||||||
}
|
}
|
||||||
for (Map.Entry<String, UUID> entry : uuidMap1.entrySet()) {
|
for (Map.Entry<String, UUID> entry : uuidMap1.entrySet()) {
|
||||||
if (entry.getKey().equalsIgnoreCase(player)) {
|
if (entry.getKey().equalsIgnoreCase(player)) {
|
||||||
uuidMap.put(player, entry.getValue());
|
try {
|
||||||
storeInfo(player, entry.getValue(), jedis);
|
uuidMap.put(entry.getKey(), entry.getValue());
|
||||||
|
} finally {
|
||||||
|
lock.writeLock().unlock();
|
||||||
|
}
|
||||||
|
storeInfo(entry.getKey(), entry.getValue(), jedis);
|
||||||
return entry.getValue();
|
return entry.getValue();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -93,11 +131,18 @@ public class UUIDTranslator {
|
|||||||
return null; // Nope, game over!
|
return null; // Nope, game over!
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getNameFromUuid(@NonNull UUID player) {
|
public String getNameFromUuid(@NonNull UUID player, boolean expensiveLookups) {
|
||||||
if (ProxyServer.getInstance().getPlayer(player) != null)
|
if (ProxyServer.getInstance().getPlayer(player) != null)
|
||||||
return ProxyServer.getInstance().getPlayer(player).getName();
|
return ProxyServer.getInstance().getPlayer(player).getName();
|
||||||
|
|
||||||
String name = uuidMap.inverse().get(player);
|
String name;
|
||||||
|
|
||||||
|
lock.readLock().lock();
|
||||||
|
try {
|
||||||
|
name = uuidMap.inverse().get(player);
|
||||||
|
} finally {
|
||||||
|
lock.readLock().unlock();
|
||||||
|
}
|
||||||
|
|
||||||
if (name != null)
|
if (name != null)
|
||||||
return name;
|
return name;
|
||||||
@ -108,10 +153,18 @@ public class UUIDTranslator {
|
|||||||
String stored = jedis.hget("player:" + player, "name");
|
String stored = jedis.hget("player:" + player, "name");
|
||||||
if (stored != null) {
|
if (stored != null) {
|
||||||
name = stored;
|
name = stored;
|
||||||
|
lock.writeLock().lock();
|
||||||
|
try {
|
||||||
uuidMap.put(name, player);
|
uuidMap.put(name, player);
|
||||||
|
} finally {
|
||||||
|
lock.writeLock().unlock();
|
||||||
|
}
|
||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!expensiveLookups)
|
||||||
|
return null;
|
||||||
|
|
||||||
// That didn't work. Let's ask Mojang.
|
// That didn't work. Let's ask Mojang.
|
||||||
try {
|
try {
|
||||||
name = new NameFetcher(Collections.singletonList(player)).call().get(player);
|
name = new NameFetcher(Collections.singletonList(player)).call().get(player);
|
||||||
@ -122,6 +175,12 @@ public class UUIDTranslator {
|
|||||||
|
|
||||||
if (name != null) {
|
if (name != null) {
|
||||||
storeInfo(name, player, jedis);
|
storeInfo(name, player, jedis);
|
||||||
|
lock.writeLock().lock();
|
||||||
|
try {
|
||||||
|
uuidMap.put(name, player);
|
||||||
|
} finally {
|
||||||
|
lock.writeLock().unlock();
|
||||||
|
}
|
||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user