Split World Data into seperate File

Allows for async WorldDataFile read and parse
This commit is contained in:
Sn0wStorm
2020-04-07 15:01:08 +02:00
parent cae2b9dfff
commit ccc0d019d5
7 changed files with 140 additions and 87 deletions
+39 -34
View File
@@ -27,26 +27,32 @@ import java.util.concurrent.atomic.AtomicInteger;
public class BData { public class BData {
public static AtomicInteger dataMutex = new AtomicInteger(0); // -1 = Saving, 0 = Free, >= 1 = Loading public static AtomicInteger dataMutex = new AtomicInteger(0); // WorldData: -1 = Saving, 0 = Free, >= 1 = Loading
public static FileConfiguration worldData = null; // World Data Cache for consecutive loading of Worlds. Nulled after a data save
// load all Data // load all Data
public static void readData() { public static void readData() {
File file = new File(P.p.getDataFolder(), "data.yml"); File file = new File(P.p.getDataFolder(), "data.yml");
if (file.exists()) { if (file.exists()) {
long t1 = System.currentTimeMillis(); long t1 = System.currentTimeMillis();
FileConfiguration data = YamlConfiguration.loadConfiguration(file); FileConfiguration data = YamlConfiguration.loadConfiguration(file);
long t2 = System.currentTimeMillis(); long t2 = System.currentTimeMillis();
if (t2 - t1 > 8000) { P.p.debugLog("Loading data.yml: " + (t2 - t1) + "ms");
// Spigot is very slow at loading inventories from yml. Notify Admin that loading Data took long
P.p.log("Bukkit took " + (t2 - t1) / 1000.0 + "s to load the Data File,"); // Check if data is the newest version
P.p.log("consider switching to Paper, or have less items in Barrels"); String version = data.getString("Version", null);
} else { if (version != null) {
P.p.debugLog("Loading data.yml: " + (t2 - t1) + "ms"); if (!version.equals(DataSave.dataVersion)) {
P.p.log("Data File is being updated...");
File worldFile = new File(P.p.getDataFolder(), "worlddata.yml");
new DataUpdater(data, file, worldFile).update(version);
data = YamlConfiguration.loadConfiguration(file);
P.p.log("Data Updated to version: " + DataSave.dataVersion);
}
} }
Brew.installTime = data.getLong("installTime", System.currentTimeMillis()); Brew.installTime = data.getLong("installTime", System.currentTimeMillis());
@@ -69,17 +75,6 @@ public class BData {
} }
} }
// Check if data is the newest version
String version = data.getString("Version", null);
if (version != null) {
if (!version.equals(DataSave.dataVersion)) {
P.p.log("Data File is being updated...");
new DataUpdater(data, file).update(version);
data = YamlConfiguration.loadConfiguration(file);
P.p.log("Data Updated to version: " + DataSave.dataVersion);
}
}
// Register Item Loaders // Register Item Loaders
CustomItem.registerItemLoader(); CustomItem.registerItemLoader();
SimpleItem.registerItemLoader(); SimpleItem.registerItemLoader();
@@ -190,24 +185,25 @@ public class BData {
} }
final FileConfiguration finalData = data;
final List<World> worlds = P.p.getServer().getWorlds(); final List<World> worlds = P.p.getServer().getWorlds();
P.p.getServer().getScheduler().runTaskAsynchronously(P.p, () -> { P.p.getServer().getScheduler().runTaskAsynchronously(P.p, () -> {
if (!acquireDataLoadMutex()) return; // Tries for 60 sec if (!acquireDataLoadMutex()) return; // Tries for 60 sec
try { try {
for (World world : worlds) { for (World world : worlds) {
P.p.log("World Init: " + world.getName());
if (world.getName().startsWith("DXL_")) { if (world.getName().startsWith("DXL_")) {
loadWorldData(BUtil.getDxlName(world.getName()), world, finalData); loadWorldData(BUtil.getDxlName(world.getName()), world);
} else { } else {
loadWorldData(world.getUID().toString(), world, finalData); loadWorldData(world.getUID().toString(), world);
} }
} }
} catch (Exception e) { } catch (Exception e) {
e.printStackTrace(); e.printStackTrace();
} finally { } finally {
releaseDataLoadMutex(); releaseDataLoadMutex();
if (BData.dataMutex.get() == 0) {
P.p.log("Background data loading complete.");
}
} }
}); });
@@ -284,12 +280,21 @@ public class BData {
// load Block locations of given world // load Block locations of given world
// can be run async // can be run async
public static void loadWorldData(String uuid, World world, FileConfiguration data) { public static void loadWorldData(String uuid, World world) {
if (BData.worldData == null) {
if (data == null) { File file = new File(P.p.getDataFolder(), "worlddata.yml");
File file = new File(P.p.getDataFolder(), "data.yml");
if (file.exists()) { if (file.exists()) {
data = YamlConfiguration.loadConfiguration(file); long t1 = System.currentTimeMillis();
BData.worldData = YamlConfiguration.loadConfiguration(file);
long t2 = System.currentTimeMillis();
if (t2 - t1 > 15000) {
// Spigot is _very_ slow at loading inventories from yml. Paper is way faster.
// Notify Admin that loading Data took long (its async so not much of a problem)
P.p.log("Bukkit took " + (t2 - t1) / 1000.0 + "s to load Inventories from the World-Data File (in the Background),");
P.p.log("consider switching to Paper, or have less items in Barrels if it takes a long time for Barrels to become available");
} else {
P.p.debugLog("Loading worlddata.yml: " + (t2 - t1) + "ms");
}
} else { } else {
return; return;
} }
@@ -297,8 +302,8 @@ public class BData {
// loading BCauldron // loading BCauldron
final Map<Block, BCauldron> initCauldrons = new HashMap<>(); final Map<Block, BCauldron> initCauldrons = new HashMap<>();
if (data.contains("BCauldron." + uuid)) { if (BData.worldData.contains("BCauldron." + uuid)) {
ConfigurationSection section = data.getConfigurationSection("BCauldron." + uuid); ConfigurationSection section = BData.worldData.getConfigurationSection("BCauldron." + uuid);
for (String cauldron : section.getKeys(false)) { for (String cauldron : section.getKeys(false)) {
// block is splitted into x/y/z // block is splitted into x/y/z
String block = section.getString(cauldron + ".block"); String block = section.getString(cauldron + ".block");
@@ -323,8 +328,8 @@ public class BData {
// loading Barrel // loading Barrel
final List<Barrel> initBarrels = new ArrayList<>(); final List<Barrel> initBarrels = new ArrayList<>();
final List<Barrel> initBadBarrels = new ArrayList<>(); final List<Barrel> initBadBarrels = new ArrayList<>();
if (data.contains("Barrel." + uuid)) { if (BData.worldData.contains("Barrel." + uuid)) {
ConfigurationSection section = data.getConfigurationSection("Barrel." + uuid); ConfigurationSection section = BData.worldData.getConfigurationSection("Barrel." + uuid);
for (String barrel : section.getKeys(false)) { for (String barrel : section.getKeys(false)) {
// block spigot is splitted into x/y/z // block spigot is splitted into x/y/z
String spigot = section.getString(barrel + ".spigot"); String spigot = section.getString(barrel + ".spigot");
@@ -391,8 +396,8 @@ public class BData {
// loading Wakeup // loading Wakeup
final List<Wakeup> initWakeups = new ArrayList<>(); final List<Wakeup> initWakeups = new ArrayList<>();
if (data.contains("Wakeup." + uuid)) { if (BData.worldData.contains("Wakeup." + uuid)) {
ConfigurationSection section = data.getConfigurationSection("Wakeup." + uuid); ConfigurationSection section = BData.worldData.getConfigurationSection("Wakeup." + uuid);
for (String wakeup : section.getKeys(false)) { for (String wakeup : section.getKeys(false)) {
// loc of wakeup is splitted into x/y/z/pitch/yaw // loc of wakeup is splitted into x/y/z/pitch/yaw
String loc = section.getString(wakeup); String loc = section.getString(wakeup);
+31 -28
View File
@@ -17,7 +17,7 @@ public class DataSave extends BukkitRunnable {
public static int lastBackup = 0; public static int lastBackup = 0;
public static int lastSave = 1; public static int lastSave = 1;
public static int autosave = 3; public static int autosave = 3;
final public static String dataVersion = "1.1"; final public static String dataVersion = "1.2";
public static DataSave running; public static DataSave running;
public ReadOldData read; public ReadOldData read;
@@ -33,10 +33,10 @@ public class DataSave extends BukkitRunnable {
@Override @Override
public void run() { public void run() {
long saveTime = System.nanoTime();
// Mutex has been acquired in ReadOldData
try { try {
FileConfiguration oldData; long saveTime = System.nanoTime();
// Mutex has been acquired in ReadOldData
FileConfiguration oldWorldData;
if (read != null) { if (read != null) {
if (!read.done) { if (!read.done) {
// Wait for async thread to load old data // Wait for async thread to load old data
@@ -52,21 +52,23 @@ public class DataSave extends BukkitRunnable {
} }
return; return;
} }
oldData = read.getData(); oldWorldData = read.getData();
} else { } else {
oldData = new YamlConfiguration(); oldWorldData = new YamlConfiguration();
} }
try { try {
cancel(); cancel();
} catch (IllegalStateException ignored) { } catch (IllegalStateException ignored) {
} }
BData.worldData = null;
FileConfiguration configFile = new YamlConfiguration(); FileConfiguration data = new YamlConfiguration();
FileConfiguration worldData = new YamlConfiguration();
configFile.set("installTime", Brew.installTime); data.set("installTime", Brew.installTime);
configFile.set("MCBarrelTime", MCBarrel.mcBarrelTime); data.set("MCBarrelTime", MCBarrel.mcBarrelTime);
Brew.writePrevSeeds(configFile); Brew.writePrevSeeds(data);
List<Integer> brewsCreated = new ArrayList<>(7); List<Integer> brewsCreated = new ArrayList<>(7);
brewsCreated.add(P.p.brewsCreated); brewsCreated.add(P.p.brewsCreated);
@@ -76,40 +78,41 @@ public class DataSave extends BukkitRunnable {
brewsCreated.add(P.p.norm); brewsCreated.add(P.p.norm);
brewsCreated.add(P.p.bad); brewsCreated.add(P.p.bad);
brewsCreated.add(P.p.terr); brewsCreated.add(P.p.terr);
configFile.set("brewsCreated", brewsCreated); data.set("brewsCreated", brewsCreated);
configFile.set("brewsCreatedH", brewsCreated.hashCode()); data.set("brewsCreatedH", brewsCreated.hashCode());
if (!Brew.legacyPotions.isEmpty()) { if (!Brew.legacyPotions.isEmpty()) {
Brew.saveLegacy(configFile.createSection("Brew")); Brew.saveLegacy(data.createSection("Brew"));
}
if (!BCauldron.bcauldrons.isEmpty() || oldData.contains("BCauldron")) {
BCauldron.save(configFile.createSection("BCauldron"), oldData.getConfigurationSection("BCauldron"));
}
if (!Barrel.barrels.isEmpty() || oldData.contains("Barrel")) {
Barrel.save(configFile.createSection("Barrel"), oldData.getConfigurationSection("Barrel"));
} }
if (!BPlayer.isEmpty()) { if (!BPlayer.isEmpty()) {
BPlayer.save(configFile.createSection("Player")); BPlayer.save(data.createSection("Player"));
} }
if (!Wakeup.wakeups.isEmpty() || oldData.contains("Wakeup")) { if (!BCauldron.bcauldrons.isEmpty() || oldWorldData.contains("BCauldron")) {
Wakeup.save(configFile.createSection("Wakeup"), oldData.getConfigurationSection("Wakeup")); BCauldron.save(worldData.createSection("BCauldron"), oldWorldData.getConfigurationSection("BCauldron"));
} }
saveWorldNames(configFile, oldData.getConfigurationSection("Worlds")); if (!Barrel.barrels.isEmpty() || oldWorldData.contains("Barrel")) {
configFile.set("Version", dataVersion); Barrel.save(worldData.createSection("Barrel"), oldWorldData.getConfigurationSection("Barrel"));
}
if (!Wakeup.wakeups.isEmpty() || oldWorldData.contains("Wakeup")) {
Wakeup.save(worldData.createSection("Wakeup"), oldWorldData.getConfigurationSection("Wakeup"));
}
saveWorldNames(worldData, oldWorldData.getConfigurationSection("Worlds"));
data.set("Version", dataVersion);
collected = true; collected = true;
P.p.debugLog("saving: " + ((System.nanoTime() - saveTime) / 1000000.0) + "ms"); P.p.debugLog("saving: " + ((System.nanoTime() - saveTime) / 1000000.0) + "ms");
if (P.p.isEnabled()) { if (P.p.isEnabled()) {
P.p.getServer().getScheduler().runTaskAsynchronously(P.p, new WriteData(configFile)); P.p.getServer().getScheduler().runTaskAsynchronously(P.p, new WriteData(data, worldData));
} else { } else {
new WriteData(configFile).run(); new WriteData(data, worldData).run();
} }
// Mutex will be released in WriteData // Mutex will be released in WriteData
} catch (Exception e) { } catch (Exception e) {
+41 -3
View File
@@ -5,6 +5,7 @@ import com.dre.brewery.P;
import org.bukkit.Material; import org.bukkit.Material;
import org.bukkit.configuration.ConfigurationSection; import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.configuration.file.FileConfiguration; import org.bukkit.configuration.file.FileConfiguration;
import org.bukkit.configuration.file.YamlConfiguration;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
@@ -15,10 +16,12 @@ public class DataUpdater {
private FileConfiguration data; private FileConfiguration data;
private File file; private File file;
private File worldFile;
public DataUpdater(FileConfiguration data, File file) { public DataUpdater(FileConfiguration data, File file, File worldFile) {
this.data = data; this.data = data;
this.file = file; this.file = file;
this.worldFile = worldFile;
} }
@@ -26,7 +29,11 @@ public class DataUpdater {
public void update(String fromVersion) { public void update(String fromVersion) {
if (fromVersion.equalsIgnoreCase("1.0")) { if (fromVersion.equalsIgnoreCase("1.0")) {
update10(); update10();
//fromVersion = "1.1"; fromVersion = "1.1";
}
if (fromVersion.equalsIgnoreCase("1.1")) {
update11();
//fromVersion = "1.2";
} }
try { try {
@@ -39,7 +46,6 @@ public class DataUpdater {
@SuppressWarnings("deprecation")
public void update10() { public void update10() {
data.set("Version", DataSave.dataVersion); data.set("Version", DataSave.dataVersion);
@@ -103,4 +109,36 @@ public class DataUpdater {
} }
} }
} }
public void update11() {
data.set("Version", DataSave.dataVersion);
FileConfiguration worldData = new YamlConfiguration();
if (data.contains("BCauldron")) {
worldData.set("BCauldron", data.get("BCauldron"));
data.set("BCauldron", null);
}
if (data.contains("Barrel")) {
worldData.set("Barrel", data.get("Barrel"));
data.set("Barrel", null);
}
if (data.contains("Wakeup")) {
worldData.set("Wakeup", data.get("Wakeup"));
data.set("Wakeup", null);
}
if (data.contains("Worlds")) {
worldData.set("Worlds", data.get("Worlds"));
data.set("Worlds", null);
}
try {
worldData.save(worldFile);
File bkup = new File(P.p.getDataFolder(), "dataBackup.yml");
if (bkup.exists()) {
bkup.renameTo(new File(P.p.getDataFolder(), "worlddataBackup.yml"));
}
} catch (IOException e) {
e.printStackTrace();
}
}
} }
+12 -8
View File
@@ -33,17 +33,21 @@ public class ReadOldData extends BukkitRunnable {
} }
File datafile = new File(P.p.getDataFolder(), "data.yml"); File worldDataFile = new File(P.p.getDataFolder(), "worlddata.yml");
if (!datafile.exists()) { if (BData.worldData == null) {
data = new YamlConfiguration(); if (!worldDataFile.exists()) {
done = true; data = new YamlConfiguration();
return; done = true;
return;
}
data = YamlConfiguration.loadConfiguration(worldDataFile);
} else {
data = BData.worldData;
} }
data = YamlConfiguration.loadConfiguration(datafile);
if (DataSave.lastBackup > 10) { if (DataSave.lastBackup > 10) {
datafile.renameTo(new File(P.p.getDataFolder(), "dataBackup.yml")); worldDataFile.renameTo(new File(P.p.getDataFolder(), "worlddataBackup.yml"));
DataSave.lastBackup = 0; DataSave.lastBackup = 0;
} else { } else {
DataSave.lastBackup++; DataSave.lastBackup++;
+9 -2
View File
@@ -2,7 +2,6 @@ package com.dre.brewery.filedata;
import java.io.File; import java.io.File;
import java.io.IOException;
import org.bukkit.configuration.file.FileConfiguration; import org.bukkit.configuration.file.FileConfiguration;
@@ -14,20 +13,28 @@ import com.dre.brewery.P;
public class WriteData implements Runnable { public class WriteData implements Runnable {
private FileConfiguration data; private FileConfiguration data;
private FileConfiguration worldData;
public WriteData(FileConfiguration data) { public WriteData(FileConfiguration data, FileConfiguration worldData) {
this.data = data; this.data = data;
this.worldData = worldData;
} }
@Override @Override
public void run() { public void run() {
File datafile = new File(P.p.getDataFolder(), "data.yml"); File datafile = new File(P.p.getDataFolder(), "data.yml");
File worlddatafile = new File(P.p.getDataFolder(), "worlddata.yml");
try { try {
data.save(datafile); data.save(datafile);
} catch (Exception e) { } catch (Exception e) {
e.printStackTrace(); e.printStackTrace();
} }
try {
worldData.save(worlddatafile);
} catch (Exception e) {
e.printStackTrace();
}
DataSave.lastSave = 1; DataSave.lastSave = 1;
DataSave.running = null; DataSave.running = null;
@@ -6,21 +6,15 @@ import com.dre.brewery.Barrel;
import com.dre.brewery.DistortChat; import com.dre.brewery.DistortChat;
import com.dre.brewery.P; import com.dre.brewery.P;
import com.dre.brewery.api.events.barrel.BarrelDestroyEvent; import com.dre.brewery.api.events.barrel.BarrelDestroyEvent;
import com.dre.brewery.filedata.BData;
import com.dre.brewery.utility.BUtil; import com.dre.brewery.utility.BUtil;
import org.bukkit.Material; import org.bukkit.Material;
import org.bukkit.Nameable;
import org.bukkit.block.Block; import org.bukkit.block.Block;
import org.bukkit.block.BlockState;
import org.bukkit.block.Container;
import org.bukkit.block.data.Directional;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler; import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority; import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener; import org.bukkit.event.Listener;
import org.bukkit.event.block.*; import org.bukkit.event.block.*;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import org.bukkit.persistence.PersistentDataType;
public class BlockListener implements Listener { public class BlockListener implements Listener {
@@ -34,6 +28,10 @@ public class BlockListener implements Listener {
P.p.msg(player, P.p.languageReader.get("Perms_NoBarrelCreate")); P.p.msg(player, P.p.languageReader.get("Perms_NoBarrelCreate"));
return; return;
} }
if (BData.dataMutex.get() > 0) {
P.p.msg(player, "§cCurrently loading Data");
return;
}
if (Barrel.create(event.getBlock(), player)) { if (Barrel.create(event.getBlock(), player)) {
P.p.msg(player, P.p.languageReader.get("Player_BarrelCreated")); P.p.msg(player, P.p.languageReader.get("Player_BarrelCreated"));
} }
@@ -4,9 +4,9 @@ import com.dre.brewery.BCauldron;
import com.dre.brewery.Barrel; import com.dre.brewery.Barrel;
import com.dre.brewery.P; import com.dre.brewery.P;
import com.dre.brewery.Wakeup; import com.dre.brewery.Wakeup;
import com.dre.brewery.utility.BUtil;
import com.dre.brewery.filedata.BData; import com.dre.brewery.filedata.BData;
import com.dre.brewery.filedata.DataSave; import com.dre.brewery.filedata.DataSave;
import com.dre.brewery.utility.BUtil;
import org.bukkit.World; import org.bukkit.World;
import org.bukkit.event.EventHandler; import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority; import org.bukkit.event.EventPriority;
@@ -19,16 +19,14 @@ public class WorldListener implements Listener {
@EventHandler @EventHandler
public void onWorldLoad(WorldLoadEvent event) { public void onWorldLoad(WorldLoadEvent event) {
final World world = event.getWorld(); final World world = event.getWorld();
P.p.log("World Load: " + event.getWorld().getName());
P.p.getServer().getScheduler().runTaskAsynchronously(P.p, () -> { P.p.getServer().getScheduler().runTaskAsynchronously(P.p, () -> {
if (!BData.acquireDataLoadMutex()) return; // Tries for 60 sec if (!BData.acquireDataLoadMutex()) return; // Tries for 60 sec
try { try {
if (world.getName().startsWith("DXL_")) { if (world.getName().startsWith("DXL_")) {
BData.loadWorldData(BUtil.getDxlName(world.getName()), world, null); BData.loadWorldData(BUtil.getDxlName(world.getName()), world);
} else { } else {
BData.loadWorldData(world.getUID().toString(), world, null); BData.loadWorldData(world.getUID().toString(), world);
} }
} catch (Exception e) { } catch (Exception e) {
e.printStackTrace(); e.printStackTrace();