Use a more efficient Name -> UUID conversion
GuntherDW opened this issue ยท 0 comments
With the current method of looping through every folder and checking every player one by one, it can take a serious amount of time to fetch all those UUID's like that.
We have about 4600 inventory yml's in our system. On our first run it was running for more than half an hour and it still didn't even get half-way.
There however is a HTTP accessible API from mojang with which you can fetch multiple UUID's at the same time. Up to 100 even.
By using evilimidget's UUIDFetcher (ready-to-implement code) the effects of this speedup really are enormous
His code can be found here : https://gist.github.com/evilmidget38/26d70114b834f71fb3b4
So then when I changed converToUUID() to something like this (Yes it can be optimised even further, but this is just to prove my point)
private void convertToUUID() {
File groupsfolder = new File(getDataFolder(), "Groups");
File uuidgroupsfolder = new File(getDataFolder(), "UUIDGroups");
groupsfolder.renameTo(uuidgroupsfolder);
List<String> playerNameList = new ArrayList<String>();
if (uuidgroupsfolder.exists() && uuidgroupsfolder.isDirectory()) {
File[] groups = uuidgroupsfolder.listFiles();
for (File gfolder : groups) {
if (gfolder.isDirectory()) {
File[] users = gfolder.listFiles();
for (File user : users) {
if (user.isFile()) {
String filename = user.getName();
if (filename.endsWith(".ec.yml")) {
String username = filename.substring(0, filename.indexOf("."));
if (!playerNameList.contains(username)) {
playerNameList.add(username);
}
} else if (filename.endsWith(".yml")) {
String username = filename.substring(0, filename.lastIndexOf("."));
if (!playerNameList.contains(username)) {
playerNameList.add(username);
}
}
}
}
}
}
}
Map<String, UUID> uuids = new HashMap<String, UUID>();
try {
com.evilmidget38.UUIDFetcher uuidFetcher = new com.evilmidget38.UUIDFetcher(playerNameList, true);
uuids = uuidFetcher.call();
} catch (Exception e) {
e.printStackTrace();
}
if (uuidgroupsfolder.exists() && uuidgroupsfolder.isDirectory()) {
File[] groups = uuidgroupsfolder.listFiles();
for (File gfolder : groups) {
if (gfolder.isDirectory()) {
File[] users = gfolder.listFiles();
for (File user : users) {
if (user.isFile()) {
String filename = user.getName();
if (filename.endsWith(".ec.yml")) {
String username = filename.substring(0, filename.indexOf("."));
String newName = "";
log.debug("Converting " + username + "'s enderchest file.");
if (uuids.containsKey(username)) {
newName = uuids.get(username).toString();
} else {
OfflinePlayer ouser = Bukkit.getOfflinePlayer(username);
newName = ouser.getUniqueId().toString();
uuids.put(username, ouser.getUniqueId());
}
File newname = new File(user.getParent(), newName + ".ec.yml");
user.renameTo(newname);
} else if (filename.endsWith(".yml")) {
String username = filename.substring(0, filename.lastIndexOf("."));
String newName = "";
log.debug("Converting " + username + "'s inventory file.");
if (uuids.containsKey(username)) {
newName = uuids.get(username).toString();
} else {
OfflinePlayer ouser = Bukkit.getOfflinePlayer(username);
newName = ouser.getUniqueId().toString();
uuids.put(username, ouser.getUniqueId());
}
File newname = new File(user.getParent(), newName + ".yml");
user.renameTo(newname);
}
}
}
}
}
}
}
The time it took to convert our ~4500-4600 yml's was less than 1 minute. Including the hits that it didn't get.
[21:45:58 INFO]: [MultiInv] Enabling MultiInv v3.3.1
[21:45:58 INFO]: [MultiInv] MC 1.3 or above found, enabling version 2 XP handling.
[21:45:58 INFO]: [MultiInv] Older data folder detected. Converting users to UUID, please wait...
[21:46:11 INFO]: Username not in map : InvictusFortis
[21:46:12 INFO]: Username not in map : johndecker
[21:46:12 INFO]: Username not in map : DutchSynapse
[21:46:12 INFO]: Username not in map : TheUberdude14.yml.bak-2014-06-05-1630
[21:46:12 INFO]: Username not in map : qazeds12
[21:46:13 INFO]: [MultiInv] Conversion complete!
Compared to 30+ minutes (and me just shutting the server down because it was taking too long) this is blazingly fast. I'm sure that if you optimise the code a bit it could get even faster, but this will help other server owners with big servers just like this I suppose. There are obvious copy/paste issues like checking for the folder twice but this is just a POC, not a beauty contest :P.