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

View File

@ -27,26 +27,32 @@ import java.util.concurrent.atomic.AtomicInteger;
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
public static void readData() {
File file = new File(P.p.getDataFolder(), "data.yml");
if (file.exists()) {
long t1 = System.currentTimeMillis();
FileConfiguration data = YamlConfiguration.loadConfiguration(file);
long t2 = System.currentTimeMillis();
if (t2 - t1 > 8000) {
// 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,");
P.p.log("consider switching to Paper, or have less items in Barrels");
} else {
P.p.debugLog("Loading data.yml: " + (t2 - t1) + "ms");
P.p.debugLog("Loading data.yml: " + (t2 - t1) + "ms");
// 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...");
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());
@ -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
CustomItem.registerItemLoader();
SimpleItem.registerItemLoader();
@ -190,24 +185,25 @@ public class BData {
}
final FileConfiguration finalData = data;
final List<World> worlds = P.p.getServer().getWorlds();
P.p.getServer().getScheduler().runTaskAsynchronously(P.p, () -> {
if (!acquireDataLoadMutex()) return; // Tries for 60 sec
try {
for (World world : worlds) {
P.p.log("World Init: " + world.getName());
if (world.getName().startsWith("DXL_")) {
loadWorldData(BUtil.getDxlName(world.getName()), world, finalData);
loadWorldData(BUtil.getDxlName(world.getName()), world);
} else {
loadWorldData(world.getUID().toString(), world, finalData);
loadWorldData(world.getUID().toString(), world);
}
}
} catch (Exception e) {
e.printStackTrace();
} finally {
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
// can be run async
public static void loadWorldData(String uuid, World world, FileConfiguration data) {
if (data == null) {
File file = new File(P.p.getDataFolder(), "data.yml");
public static void loadWorldData(String uuid, World world) {
if (BData.worldData == null) {
File file = new File(P.p.getDataFolder(), "worlddata.yml");
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 {
return;
}
@ -297,8 +302,8 @@ public class BData {
// loading BCauldron
final Map<Block, BCauldron> initCauldrons = new HashMap<>();
if (data.contains("BCauldron." + uuid)) {
ConfigurationSection section = data.getConfigurationSection("BCauldron." + uuid);
if (BData.worldData.contains("BCauldron." + uuid)) {
ConfigurationSection section = BData.worldData.getConfigurationSection("BCauldron." + uuid);
for (String cauldron : section.getKeys(false)) {
// block is splitted into x/y/z
String block = section.getString(cauldron + ".block");
@ -323,8 +328,8 @@ public class BData {
// loading Barrel
final List<Barrel> initBarrels = new ArrayList<>();
final List<Barrel> initBadBarrels = new ArrayList<>();
if (data.contains("Barrel." + uuid)) {
ConfigurationSection section = data.getConfigurationSection("Barrel." + uuid);
if (BData.worldData.contains("Barrel." + uuid)) {
ConfigurationSection section = BData.worldData.getConfigurationSection("Barrel." + uuid);
for (String barrel : section.getKeys(false)) {
// block spigot is splitted into x/y/z
String spigot = section.getString(barrel + ".spigot");
@ -391,8 +396,8 @@ public class BData {
// loading Wakeup
final List<Wakeup> initWakeups = new ArrayList<>();
if (data.contains("Wakeup." + uuid)) {
ConfigurationSection section = data.getConfigurationSection("Wakeup." + uuid);
if (BData.worldData.contains("Wakeup." + uuid)) {
ConfigurationSection section = BData.worldData.getConfigurationSection("Wakeup." + uuid);
for (String wakeup : section.getKeys(false)) {
// loc of wakeup is splitted into x/y/z/pitch/yaw
String loc = section.getString(wakeup);

View File

@ -17,7 +17,7 @@ public class DataSave extends BukkitRunnable {
public static int lastBackup = 0;
public static int lastSave = 1;
public static int autosave = 3;
final public static String dataVersion = "1.1";
final public static String dataVersion = "1.2";
public static DataSave running;
public ReadOldData read;
@ -33,10 +33,10 @@ public class DataSave extends BukkitRunnable {
@Override
public void run() {
long saveTime = System.nanoTime();
// Mutex has been acquired in ReadOldData
try {
FileConfiguration oldData;
long saveTime = System.nanoTime();
// Mutex has been acquired in ReadOldData
FileConfiguration oldWorldData;
if (read != null) {
if (!read.done) {
// Wait for async thread to load old data
@ -52,21 +52,23 @@ public class DataSave extends BukkitRunnable {
}
return;
}
oldData = read.getData();
oldWorldData = read.getData();
} else {
oldData = new YamlConfiguration();
oldWorldData = new YamlConfiguration();
}
try {
cancel();
} catch (IllegalStateException ignored) {
}
BData.worldData = null;
FileConfiguration configFile = new YamlConfiguration();
FileConfiguration data = new YamlConfiguration();
FileConfiguration worldData = new YamlConfiguration();
configFile.set("installTime", Brew.installTime);
configFile.set("MCBarrelTime", MCBarrel.mcBarrelTime);
data.set("installTime", Brew.installTime);
data.set("MCBarrelTime", MCBarrel.mcBarrelTime);
Brew.writePrevSeeds(configFile);
Brew.writePrevSeeds(data);
List<Integer> brewsCreated = new ArrayList<>(7);
brewsCreated.add(P.p.brewsCreated);
@ -76,40 +78,41 @@ public class DataSave extends BukkitRunnable {
brewsCreated.add(P.p.norm);
brewsCreated.add(P.p.bad);
brewsCreated.add(P.p.terr);
configFile.set("brewsCreated", brewsCreated);
configFile.set("brewsCreatedH", brewsCreated.hashCode());
data.set("brewsCreated", brewsCreated);
data.set("brewsCreatedH", brewsCreated.hashCode());
if (!Brew.legacyPotions.isEmpty()) {
Brew.saveLegacy(configFile.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"));
Brew.saveLegacy(data.createSection("Brew"));
}
if (!BPlayer.isEmpty()) {
BPlayer.save(configFile.createSection("Player"));
BPlayer.save(data.createSection("Player"));
}
if (!Wakeup.wakeups.isEmpty() || oldData.contains("Wakeup")) {
Wakeup.save(configFile.createSection("Wakeup"), oldData.getConfigurationSection("Wakeup"));
if (!BCauldron.bcauldrons.isEmpty() || oldWorldData.contains("BCauldron")) {
BCauldron.save(worldData.createSection("BCauldron"), oldWorldData.getConfigurationSection("BCauldron"));
}
saveWorldNames(configFile, oldData.getConfigurationSection("Worlds"));
configFile.set("Version", dataVersion);
if (!Barrel.barrels.isEmpty() || oldWorldData.contains("Barrel")) {
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;
P.p.debugLog("saving: " + ((System.nanoTime() - saveTime) / 1000000.0) + "ms");
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 {
new WriteData(configFile).run();
new WriteData(data, worldData).run();
}
// Mutex will be released in WriteData
} catch (Exception e) {

View File

@ -5,6 +5,7 @@ import com.dre.brewery.P;
import org.bukkit.Material;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.configuration.file.FileConfiguration;
import org.bukkit.configuration.file.YamlConfiguration;
import java.io.File;
import java.io.IOException;
@ -15,10 +16,12 @@ public class DataUpdater {
private FileConfiguration data;
private File file;
private File worldFile;
public DataUpdater(FileConfiguration data, File file) {
public DataUpdater(FileConfiguration data, File file, File worldFile) {
this.data = data;
this.file = file;
this.worldFile = worldFile;
}
@ -26,7 +29,11 @@ public class DataUpdater {
public void update(String fromVersion) {
if (fromVersion.equalsIgnoreCase("1.0")) {
update10();
//fromVersion = "1.1";
fromVersion = "1.1";
}
if (fromVersion.equalsIgnoreCase("1.1")) {
update11();
//fromVersion = "1.2";
}
try {
@ -39,7 +46,6 @@ public class DataUpdater {
@SuppressWarnings("deprecation")
public void update10() {
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();
}
}
}

View File

@ -33,17 +33,21 @@ public class ReadOldData extends BukkitRunnable {
}
File datafile = new File(P.p.getDataFolder(), "data.yml");
if (!datafile.exists()) {
data = new YamlConfiguration();
done = true;
return;
File worldDataFile = new File(P.p.getDataFolder(), "worlddata.yml");
if (BData.worldData == null) {
if (!worldDataFile.exists()) {
data = new YamlConfiguration();
done = true;
return;
}
data = YamlConfiguration.loadConfiguration(worldDataFile);
} else {
data = BData.worldData;
}
data = YamlConfiguration.loadConfiguration(datafile);
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;
} else {
DataSave.lastBackup++;

View File

@ -2,7 +2,6 @@ package com.dre.brewery.filedata;
import java.io.File;
import java.io.IOException;
import org.bukkit.configuration.file.FileConfiguration;
@ -14,20 +13,28 @@ import com.dre.brewery.P;
public class WriteData implements Runnable {
private FileConfiguration data;
private FileConfiguration worldData;
public WriteData(FileConfiguration data) {
public WriteData(FileConfiguration data, FileConfiguration worldData) {
this.data = data;
this.worldData = worldData;
}
@Override
public void run() {
File datafile = new File(P.p.getDataFolder(), "data.yml");
File worlddatafile = new File(P.p.getDataFolder(), "worlddata.yml");
try {
data.save(datafile);
} catch (Exception e) {
e.printStackTrace();
}
try {
worldData.save(worlddatafile);
} catch (Exception e) {
e.printStackTrace();
}
DataSave.lastSave = 1;
DataSave.running = null;

View File

@ -6,21 +6,15 @@ import com.dre.brewery.Barrel;
import com.dre.brewery.DistortChat;
import com.dre.brewery.P;
import com.dre.brewery.api.events.barrel.BarrelDestroyEvent;
import com.dre.brewery.filedata.BData;
import com.dre.brewery.utility.BUtil;
import org.bukkit.Material;
import org.bukkit.Nameable;
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.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
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 {
@ -34,6 +28,10 @@ public class BlockListener implements Listener {
P.p.msg(player, P.p.languageReader.get("Perms_NoBarrelCreate"));
return;
}
if (BData.dataMutex.get() > 0) {
P.p.msg(player, "§cCurrently loading Data");
return;
}
if (Barrel.create(event.getBlock(), player)) {
P.p.msg(player, P.p.languageReader.get("Player_BarrelCreated"));
}

View File

@ -4,9 +4,9 @@ import com.dre.brewery.BCauldron;
import com.dre.brewery.Barrel;
import com.dre.brewery.P;
import com.dre.brewery.Wakeup;
import com.dre.brewery.utility.BUtil;
import com.dre.brewery.filedata.BData;
import com.dre.brewery.filedata.DataSave;
import com.dre.brewery.utility.BUtil;
import org.bukkit.World;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
@ -19,16 +19,14 @@ public class WorldListener implements Listener {
@EventHandler
public void onWorldLoad(WorldLoadEvent event) {
final World world = event.getWorld();
P.p.log("World Load: " + event.getWorld().getName());
P.p.getServer().getScheduler().runTaskAsynchronously(P.p, () -> {
if (!BData.acquireDataLoadMutex()) return; // Tries for 60 sec
try {
if (world.getName().startsWith("DXL_")) {
BData.loadWorldData(BUtil.getDxlName(world.getName()), world, null);
BData.loadWorldData(BUtil.getDxlName(world.getName()), world);
} else {
BData.loadWorldData(world.getUID().toString(), world, null);
BData.loadWorldData(world.getUID().toString(), world);
}
} catch (Exception e) {
e.printStackTrace();