mirror of
https://github.com/essentials/Essentials.git
synced 2025-08-11 09:05:01 +02:00
Queued writing of the files to reduce disk io
This commit is contained in:
@@ -24,6 +24,7 @@ import java.util.List;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import static net.ess3.I18n._;
|
||||
import net.ess3.api.*;
|
||||
import net.ess3.backup.Backup;
|
||||
@@ -36,6 +37,7 @@ import net.ess3.metrics.Metrics;
|
||||
import net.ess3.ranks.RanksStorage;
|
||||
import net.ess3.settings.SettingsHolder;
|
||||
import net.ess3.settings.SpawnsHolder;
|
||||
import net.ess3.storage.StorageQueue;
|
||||
import net.ess3.user.UserMap;
|
||||
import net.ess3.utils.ExecuteTimer;
|
||||
import org.bukkit.Server;
|
||||
@@ -46,22 +48,34 @@ import org.bukkit.plugin.InvalidDescriptionException;
|
||||
|
||||
public class Essentials implements IEssentials
|
||||
{
|
||||
@Getter
|
||||
private transient ISettings settings;
|
||||
@Getter
|
||||
private transient IJails jails;
|
||||
@Getter
|
||||
private transient IKits kits;
|
||||
@Getter
|
||||
private transient IWarps warps;
|
||||
@Getter
|
||||
private transient IWorth worth;
|
||||
private transient List<IReload> reloadList;
|
||||
@Getter
|
||||
private transient IBackup backup;
|
||||
@Getter
|
||||
private transient IItemDb itemDb;
|
||||
private transient IRanks groups;
|
||||
@Getter
|
||||
@Setter
|
||||
private transient IRanks ranks;
|
||||
@Getter
|
||||
private transient SpawnsHolder spawns;
|
||||
@Getter
|
||||
private transient final Methods paymentMethod = new Methods();
|
||||
@Getter
|
||||
private transient IUserMap userMap;
|
||||
private transient ExecuteTimer execTimer;
|
||||
@Getter
|
||||
private final I18n i18n;
|
||||
@Getter
|
||||
private transient ICommandHandler commandHandler;
|
||||
@Getter
|
||||
private transient Economy economy;
|
||||
@Getter
|
||||
private final Server server;
|
||||
@@ -69,28 +83,29 @@ public class Essentials implements IEssentials
|
||||
private final Logger logger;
|
||||
@Getter
|
||||
private final IPlugin plugin;
|
||||
public static boolean testing;
|
||||
@Getter
|
||||
@Setter
|
||||
private transient Metrics metrics;
|
||||
@Getter
|
||||
private transient EssentialsTimer timer;
|
||||
@Getter
|
||||
private transient List<String> vanishedPlayers = new ArrayList<String>();
|
||||
@Getter
|
||||
private final transient StorageQueue storageQueue;
|
||||
private transient ExecuteTimer execTimer;
|
||||
public static boolean testing;
|
||||
private transient List<IReload> reloadList;
|
||||
|
||||
public Essentials(final Server server, final Logger logger, final IPlugin plugin)
|
||||
{
|
||||
this.server = server;
|
||||
this.logger = logger;
|
||||
this.plugin = plugin;
|
||||
this.storageQueue = new StorageQueue(plugin);
|
||||
this.i18n = new I18n(this);
|
||||
i18n.onEnable();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ISettings getSettings()
|
||||
{
|
||||
return settings;
|
||||
}
|
||||
|
||||
public void setupForTesting(final Server server) throws IOException, InvalidDescriptionException
|
||||
{
|
||||
testing = true;
|
||||
@@ -106,6 +121,7 @@ public class Essentials implements IEssentials
|
||||
|
||||
logger.log(Level.INFO, I18n._("usingTempFolderForTesting"));
|
||||
logger.log(Level.INFO, dataFolder.toString());
|
||||
storageQueue.setEnabled(true);
|
||||
settings = new SettingsHolder(this);
|
||||
i18n.updateLocale("en");
|
||||
userMap = new UserMap(this);
|
||||
@@ -115,6 +131,7 @@ public class Essentials implements IEssentials
|
||||
@Override
|
||||
public void onEnable()
|
||||
{
|
||||
storageQueue.setEnabled(true);
|
||||
execTimer = new ExecuteTimer();
|
||||
execTimer.start();
|
||||
|
||||
@@ -130,8 +147,8 @@ public class Essentials implements IEssentials
|
||||
userMap = new UserMap(this);
|
||||
reloadList.add(userMap);
|
||||
execTimer.mark("Init(Usermap)");
|
||||
groups = new RanksStorage(this);
|
||||
reloadList.add((RanksStorage)groups);
|
||||
ranks = new RanksStorage(this);
|
||||
reloadList.add((RanksStorage)ranks);
|
||||
warps = new Warps(this);
|
||||
reloadList.add(warps);
|
||||
execTimer.mark("Init(Spawn/Warp)");
|
||||
@@ -181,6 +198,7 @@ public class Essentials implements IEssentials
|
||||
}
|
||||
i18n.onDisable();
|
||||
Trade.closeLog();
|
||||
storageQueue.setEnabled(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -197,48 +215,6 @@ public class Essentials implements IEssentials
|
||||
i18n.updateLocale(settings.getLocale());
|
||||
}
|
||||
|
||||
@Override
|
||||
public IJails getJails()
|
||||
{
|
||||
return jails;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IKits getKits()
|
||||
{
|
||||
return kits;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IWarps getWarps()
|
||||
{
|
||||
return warps;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IWorth getWorth()
|
||||
{
|
||||
return worth;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IBackup getBackup()
|
||||
{
|
||||
return backup;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Metrics getMetrics()
|
||||
{
|
||||
return metrics;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setMetrics(Metrics metrics)
|
||||
{
|
||||
this.metrics = metrics;
|
||||
}
|
||||
|
||||
@Override
|
||||
public World getWorld(final String name)
|
||||
{
|
||||
@@ -259,12 +235,6 @@ public class Essentials implements IEssentials
|
||||
reloadList.add(listener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Methods getPaymentMethod()
|
||||
{
|
||||
return paymentMethod;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int broadcastMessage(final IUser sender, final String message)
|
||||
{
|
||||
@@ -288,57 +258,9 @@ public class Essentials implements IEssentials
|
||||
return getServer().getOnlinePlayers().length;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IItemDb getItemDb()
|
||||
{
|
||||
return itemDb;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IUserMap getUserMap()
|
||||
{
|
||||
return userMap;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IRanks getRanks()
|
||||
{
|
||||
return groups;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ICommandHandler getCommandHandler()
|
||||
{
|
||||
return commandHandler;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setRanks(final IRanks groups)
|
||||
{
|
||||
this.groups = groups;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeReloadListener(IReload groups)
|
||||
{
|
||||
this.reloadList.remove(groups);
|
||||
}
|
||||
|
||||
@Override
|
||||
public IEconomy getEconomy()
|
||||
{
|
||||
return economy;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SpawnsHolder getSpawns()
|
||||
{
|
||||
return spawns;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reload()
|
||||
{
|
||||
//do something
|
||||
}
|
||||
}
|
||||
|
@@ -31,7 +31,7 @@ public class Jails extends AsyncStorageObjectHolder<net.ess3.settings.Jails> imp
|
||||
|
||||
public Jails(final IEssentials ess)
|
||||
{
|
||||
super(ess, net.ess3.settings.Jails.class);
|
||||
super(ess, net.ess3.settings.Jails.class, new File(ess.getPlugin().getDataFolder(), "jail.yml"));
|
||||
onReload();
|
||||
registerListeners();
|
||||
}
|
||||
@@ -45,12 +45,6 @@ public class Jails extends AsyncStorageObjectHolder<net.ess3.settings.Jails> imp
|
||||
pluginManager.registerEvents(playerListener, ess.getPlugin());
|
||||
}
|
||||
|
||||
@Override
|
||||
public File getStorageFile()
|
||||
{
|
||||
return new File(ess.getPlugin().getDataFolder(), "jail.yml");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Location getJail(final String jailName) throws Exception
|
||||
{
|
||||
|
@@ -19,16 +19,10 @@ public class Kits extends AsyncStorageObjectHolder<net.ess3.settings.Kits> imple
|
||||
{
|
||||
public Kits(final IEssentials ess)
|
||||
{
|
||||
super(ess, net.ess3.settings.Kits.class);
|
||||
super(ess, net.ess3.settings.Kits.class, new File(ess.getPlugin().getDataFolder(), "kits.yml"));
|
||||
onReload();
|
||||
}
|
||||
|
||||
@Override
|
||||
public File getStorageFile() throws IOException
|
||||
{
|
||||
return new File(ess.getPlugin().getDataFolder(), "kits.yml");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Kit getKit(String kitName) throws Exception
|
||||
{
|
||||
|
@@ -6,6 +6,7 @@ import net.ess3.EssentialsTimer;
|
||||
import net.ess3.economy.register.Methods;
|
||||
import net.ess3.metrics.Metrics;
|
||||
import net.ess3.settings.SpawnsHolder;
|
||||
import net.ess3.storage.StorageQueue;
|
||||
import org.bukkit.Server;
|
||||
import org.bukkit.World;
|
||||
|
||||
@@ -42,8 +43,6 @@ public interface IEssentials extends IComponent
|
||||
|
||||
Methods getPaymentMethod();
|
||||
|
||||
void reload();
|
||||
|
||||
void setRanks(IRanks groups);
|
||||
|
||||
void removeReloadListener(IReload groups);
|
||||
@@ -65,4 +64,6 @@ public interface IEssentials extends IComponent
|
||||
void setMetrics(Metrics metrics);
|
||||
|
||||
SpawnsHolder getSpawns();
|
||||
|
||||
StorageQueue getStorageQueue();
|
||||
}
|
||||
|
@@ -51,7 +51,7 @@ public class Commandessentials extends EssentialsCommand
|
||||
|
||||
private void run_reload(final CommandSender sender, final String[] args) throws Exception
|
||||
{
|
||||
ess.reload();
|
||||
ess.onReload();
|
||||
sender.sendMessage(_("essentialsReload", ess.getPlugin().getVersion()));
|
||||
}
|
||||
}
|
||||
|
@@ -1,7 +1,6 @@
|
||||
package net.ess3.economy;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import net.ess3.api.IEssentials;
|
||||
import net.ess3.storage.AsyncStorageObjectHolder;
|
||||
|
||||
@@ -24,13 +23,7 @@ public class MoneyHolder extends AsyncStorageObjectHolder<Money>
|
||||
|
||||
public MoneyHolder(IEssentials ess)
|
||||
{
|
||||
super(ess, Money.class);
|
||||
super(ess, Money.class, new File(ess.getPlugin().getDataFolder(), "economy_npcs.yml"));
|
||||
onReload();
|
||||
}
|
||||
|
||||
@Override
|
||||
public File getStorageFile() throws IOException
|
||||
{
|
||||
return new File(ess.getPlugin().getDataFolder(), "economy_npcs.yml");
|
||||
}
|
||||
}
|
||||
|
@@ -26,7 +26,7 @@ public class WorthHolder extends AsyncStorageObjectHolder<net.ess3.economy.Worth
|
||||
|
||||
public WorthHolder(final IEssentials ess)
|
||||
{
|
||||
super(ess, net.ess3.economy.Worth.class);
|
||||
super(ess, net.ess3.economy.Worth.class, new File(ess.getPlugin().getDataFolder(), "worth.yml"));
|
||||
onReload(false);
|
||||
}
|
||||
|
||||
@@ -72,10 +72,4 @@ public class WorthHolder extends AsyncStorageObjectHolder<net.ess3.economy.Worth
|
||||
getData().setSellPrice(itemStack.getData(), price);
|
||||
queueSave();
|
||||
}
|
||||
|
||||
@Override
|
||||
public File getStorageFile() throws IOException
|
||||
{
|
||||
return new File(ess.getPlugin().getDataFolder(), "worth.yml");
|
||||
}
|
||||
}
|
||||
|
@@ -30,16 +30,10 @@ public class RanksStorage extends AsyncStorageObjectHolder<Ranks> implements IRa
|
||||
|
||||
public RanksStorage(final IEssentials ess)
|
||||
{
|
||||
super(ess, Ranks.class);
|
||||
super(ess, Ranks.class, new File(ess.getPlugin().getDataFolder(), "ranks.yml"));
|
||||
onReload();
|
||||
}
|
||||
|
||||
@Override
|
||||
public File getStorageFile()
|
||||
{
|
||||
return new File(ess.getPlugin().getDataFolder(), "ranks.yml");
|
||||
}
|
||||
|
||||
public Collection<Entry<String, RankOptions>> getGroups(final IUser player)
|
||||
{
|
||||
final Map<String, RankOptions> groups = getData().getRanks();
|
||||
|
@@ -21,7 +21,7 @@ public class SettingsHolder extends AsyncStorageObjectHolder<Settings> implement
|
||||
|
||||
public SettingsHolder(final IEssentials ess)
|
||||
{
|
||||
super(ess, Settings.class);
|
||||
super(ess, Settings.class, new File(ess.getPlugin().getDataFolder(), "settings.yml"));
|
||||
onReload();
|
||||
}
|
||||
|
||||
@@ -33,12 +33,6 @@ public class SettingsHolder extends AsyncStorageObjectHolder<Settings> implement
|
||||
debug = getData().getGeneral().isDebug();
|
||||
}
|
||||
|
||||
@Override
|
||||
public File getStorageFile()
|
||||
{
|
||||
return new File(ess.getPlugin().getDataFolder(), "settings.yml");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getLocale()
|
||||
{
|
||||
|
@@ -40,17 +40,11 @@ public class SpawnsHolder extends AsyncStorageObjectHolder<Spawns> implements IE
|
||||
|
||||
public SpawnsHolder(final IEssentials ess)
|
||||
{
|
||||
super(ess, Spawns.class);
|
||||
super(ess, Spawns.class, new File(ess.getPlugin().getDataFolder(), "spawn.yml"));
|
||||
onReload();
|
||||
registerListeners();
|
||||
}
|
||||
|
||||
@Override
|
||||
public File getStorageFile()
|
||||
{
|
||||
return new File(ess.getPlugin().getDataFolder(), "spawn.yml");
|
||||
}
|
||||
|
||||
public void setSpawn(final Location loc, final String group)
|
||||
{
|
||||
getData().addSpawn(group, loc);
|
||||
|
@@ -1,7 +1,5 @@
|
||||
package net.ess3.settings;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import net.ess3.api.IEssentials;
|
||||
import net.ess3.api.IWarp;
|
||||
import net.ess3.api.InvalidNameException;
|
||||
@@ -10,39 +8,21 @@ import net.ess3.storage.AsyncStorageObjectHolder;
|
||||
|
||||
public class WarpHolder extends AsyncStorageObjectHolder<Warp> implements IWarp
|
||||
{
|
||||
|
||||
@Override
|
||||
public void finishRead()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void finishWrite()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
private final String name;
|
||||
|
||||
public WarpHolder(String name, IEssentials ess)
|
||||
public WarpHolder(String name, IEssentials ess) throws InvalidNameException
|
||||
{
|
||||
super(ess, Warp.class);
|
||||
super(ess, Warp.class, ess.getWarps().getWarpFile(name));
|
||||
this.name = name;
|
||||
onReload();
|
||||
}
|
||||
|
||||
@Override
|
||||
public File getStorageFile() throws IOException
|
||||
{
|
||||
try
|
||||
{
|
||||
return ess.getWarps().getWarpFile(name);
|
||||
}
|
||||
catch (InvalidNameException ex)
|
||||
{
|
||||
throw new IOException(ex.getMessage(), ex);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -4,7 +4,6 @@ import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.FileReader;
|
||||
import java.io.IOException;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
import java.util.logging.Level;
|
||||
import net.ess3.api.IEssentials;
|
||||
import org.bukkit.Bukkit;
|
||||
@@ -12,10 +11,8 @@ import org.bukkit.Bukkit;
|
||||
|
||||
public abstract class AbstractDelayedYamlFileReader<T extends StorageObject> implements Runnable
|
||||
{
|
||||
|
||||
private final transient Class<T> clazz;
|
||||
private final transient IEssentials ess;
|
||||
private final transient ReentrantLock lock = new ReentrantLock();
|
||||
|
||||
public AbstractDelayedYamlFileReader(final IEssentials ess, final Class<T> clazz)
|
||||
{
|
||||
@@ -35,16 +32,14 @@ public abstract class AbstractDelayedYamlFileReader<T extends StorageObject> imp
|
||||
}
|
||||
}
|
||||
|
||||
public abstract File onStart() throws IOException;
|
||||
public abstract File onStart();
|
||||
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
File file = null;
|
||||
lock.lock();
|
||||
try
|
||||
final File file = onStart();
|
||||
synchronized (file)
|
||||
{
|
||||
file = onStart();
|
||||
try
|
||||
{
|
||||
final FileReader reader = new FileReader(file);
|
||||
@@ -69,7 +64,7 @@ public abstract class AbstractDelayedYamlFileReader<T extends StorageObject> imp
|
||||
catch (FileNotFoundException ex)
|
||||
{
|
||||
onException(ex);
|
||||
Bukkit.getLogger().log(Level.INFO, "File not found: {0}", file.toString());
|
||||
Bukkit.getLogger().log(Level.INFO, "File not found: " + file.toString());
|
||||
}
|
||||
catch (ObjectLoadException ex)
|
||||
{
|
||||
@@ -79,18 +74,6 @@ public abstract class AbstractDelayedYamlFileReader<T extends StorageObject> imp
|
||||
Bukkit.getLogger().log(Level.SEVERE, "The file " + file.toString() + " is broken, it has been renamed to " + broken.toString(), ex.getCause());
|
||||
}
|
||||
}
|
||||
catch (IOException ex)
|
||||
{
|
||||
onException(ex);
|
||||
if (ess.getSettings() == null || ess.getSettings().isDebug())
|
||||
{
|
||||
Bukkit.getLogger().log(Level.INFO, "File not found: " + file.toString());
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
public abstract void onSuccess(T object);
|
||||
|
@@ -2,7 +2,6 @@ package net.ess3.storage;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.io.PrintWriter;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
import java.util.logging.Level;
|
||||
@@ -25,17 +24,16 @@ public abstract class AbstractDelayedYamlFileWriter implements Runnable
|
||||
ess.getPlugin().scheduleAsyncDelayedTask(this);
|
||||
}
|
||||
|
||||
public abstract File getFile() throws IOException;
|
||||
public abstract File getFile();
|
||||
|
||||
public abstract StorageObject getObject();
|
||||
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
lock.lock();
|
||||
try
|
||||
{
|
||||
final File file = getFile();
|
||||
synchronized (file)
|
||||
{
|
||||
PrintWriter pw = null;
|
||||
try
|
||||
{
|
||||
@@ -61,14 +59,6 @@ public abstract class AbstractDelayedYamlFileWriter implements Runnable
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (IOException ex)
|
||||
{
|
||||
Bukkit.getLogger().log(Level.SEVERE, ex.getMessage(), ex);
|
||||
}
|
||||
finally
|
||||
{
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
public abstract void onFinish();
|
||||
|
@@ -4,6 +4,8 @@ import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.concurrent.locks.Lock;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
import java.util.logging.Level;
|
||||
import net.ess3.api.IEssentials;
|
||||
import org.bukkit.Bukkit;
|
||||
@@ -17,11 +19,14 @@ public abstract class AsyncStorageObjectHolder<T extends StorageObject> implemen
|
||||
private final transient StorageObjectDataWriter writer;
|
||||
private final transient StorageObjectDataReader reader;
|
||||
private final transient AtomicBoolean loaded = new AtomicBoolean(false);
|
||||
private volatile long savetime = 0;
|
||||
private final transient File file;
|
||||
|
||||
public AsyncStorageObjectHolder(final IEssentials ess, final Class<T> clazz)
|
||||
public AsyncStorageObjectHolder(final IEssentials ess, final Class<T> clazz, final File file)
|
||||
{
|
||||
this.ess = ess;
|
||||
this.clazz = clazz;
|
||||
this.file = file;
|
||||
writer = new StorageObjectDataWriter();
|
||||
reader = new StorageObjectDataReader();
|
||||
try
|
||||
@@ -53,7 +58,7 @@ public abstract class AsyncStorageObjectHolder<T extends StorageObject> implemen
|
||||
@Override
|
||||
public void queueSave()
|
||||
{
|
||||
writer.schedule();
|
||||
ess.getStorageQueue().queue(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -67,12 +72,41 @@ public abstract class AsyncStorageObjectHolder<T extends StorageObject> implemen
|
||||
reader.schedule(instant);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return file.getAbsolutePath();
|
||||
}
|
||||
|
||||
public abstract void finishRead();
|
||||
|
||||
public abstract void finishWrite();
|
||||
|
||||
public abstract File getStorageFile() throws IOException;
|
||||
public StorageQueue.RequestState getRequestState(long timestamp)
|
||||
{
|
||||
if (savetime == 0 || savetime < timestamp || (timestamp < 0 && savetime > 0))
|
||||
{
|
||||
final long now = System.nanoTime();
|
||||
if (Math.abs(now - savetime) < StorageQueue.DELAY)
|
||||
{
|
||||
return StorageQueue.RequestState.REQUEUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
savetime = System.nanoTime();
|
||||
return StorageQueue.RequestState.SCHEDULE;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return StorageQueue.RequestState.FINISHED;
|
||||
}
|
||||
}
|
||||
|
||||
Runnable getFileWriter()
|
||||
{
|
||||
return writer;
|
||||
}
|
||||
|
||||
private class StorageObjectDataWriter extends AbstractDelayedYamlFileWriter
|
||||
{
|
||||
@@ -82,9 +116,9 @@ public abstract class AsyncStorageObjectHolder<T extends StorageObject> implemen
|
||||
}
|
||||
|
||||
@Override
|
||||
public File getFile() throws IOException
|
||||
public File getFile()
|
||||
{
|
||||
return getStorageFile();
|
||||
return file;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -109,9 +143,9 @@ public abstract class AsyncStorageObjectHolder<T extends StorageObject> implemen
|
||||
}
|
||||
|
||||
@Override
|
||||
public File onStart() throws IOException
|
||||
public File onStart()
|
||||
{
|
||||
return getStorageFile();
|
||||
return file;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -122,6 +156,7 @@ public abstract class AsyncStorageObjectHolder<T extends StorageObject> implemen
|
||||
data = object;
|
||||
}
|
||||
loaded.set(true);
|
||||
finishRead();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
141
Essentials/src/net/ess3/storage/StorageQueue.java
Normal file
141
Essentials/src/net/ess3/storage/StorageQueue.java
Normal file
@@ -0,0 +1,141 @@
|
||||
package net.ess3.storage;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.DelayQueue;
|
||||
import java.util.concurrent.Delayed;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
import net.ess3.api.IPlugin;
|
||||
|
||||
|
||||
public class StorageQueue implements Runnable
|
||||
{
|
||||
private DelayQueue<WriteRequest> queue = new DelayQueue<WriteRequest>();
|
||||
public final static long DELAY = TimeUnit.NANOSECONDS.convert(1, TimeUnit.SECONDS);
|
||||
private final AtomicBoolean enabled = new AtomicBoolean(false);
|
||||
private final transient Object lock = new Object();
|
||||
private final IPlugin plugin;
|
||||
|
||||
public StorageQueue(IPlugin plugin)
|
||||
{
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
synchronized (lock)
|
||||
{
|
||||
List<WriteRequest> requests = new ArrayList<WriteRequest>();
|
||||
while (enabled.get() || !queue.isEmpty())
|
||||
{
|
||||
try
|
||||
{
|
||||
queue.drainTo(requests);
|
||||
for (WriteRequest request : requests)
|
||||
{
|
||||
RequestState state = request.getRequestState();
|
||||
if (state == RequestState.REQUEUE)
|
||||
{
|
||||
queue.add(request);
|
||||
continue;
|
||||
}
|
||||
if (state == RequestState.SCHEDULE)
|
||||
{
|
||||
plugin.scheduleAsyncDelayedTask(request.getRunnable());
|
||||
}
|
||||
}
|
||||
requests.clear();
|
||||
Thread.sleep(100);
|
||||
}
|
||||
catch (InterruptedException ex)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void queue(AsyncStorageObjectHolder objectHolder)
|
||||
{
|
||||
if (!enabled.get())
|
||||
{
|
||||
plugin.getLogger().log(Level.SEVERE,
|
||||
"File " + objectHolder.toString() + " is queued for saving, while the queue is disabled. It's possible that it will not be saved!",
|
||||
new RuntimeException());
|
||||
}
|
||||
queue.add(new WriteRequest(objectHolder));
|
||||
}
|
||||
|
||||
private void startThread()
|
||||
{
|
||||
synchronized (lock)
|
||||
{
|
||||
plugin.scheduleAsyncDelayedTask(this);
|
||||
}
|
||||
}
|
||||
|
||||
public void setEnabled(boolean enabled)
|
||||
{
|
||||
if (this.enabled.getAndSet(enabled) != enabled && enabled)
|
||||
{
|
||||
startThread();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private class WriteRequest implements Delayed
|
||||
{
|
||||
private final AsyncStorageObjectHolder objectHolder;
|
||||
private final long timestamp;
|
||||
|
||||
public WriteRequest(AsyncStorageObjectHolder objectHolder)
|
||||
{
|
||||
this.objectHolder = objectHolder;
|
||||
this.timestamp = System.nanoTime();
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getDelay(final TimeUnit tu)
|
||||
{
|
||||
if (tu == TimeUnit.NANOSECONDS)
|
||||
{
|
||||
final long now = System.nanoTime();
|
||||
return DELAY - Math.abs(now - timestamp);
|
||||
}
|
||||
else
|
||||
{
|
||||
return tu.convert(getDelay(TimeUnit.NANOSECONDS), TimeUnit.NANOSECONDS);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(final Delayed t)
|
||||
{
|
||||
final long a = getDelay(TimeUnit.NANOSECONDS);
|
||||
final long b = t.getDelay(TimeUnit.NANOSECONDS);
|
||||
return a < b ? -1 : a == b ? 0 : 1;
|
||||
}
|
||||
|
||||
public RequestState getRequestState()
|
||||
{
|
||||
return objectHolder.getRequestState(timestamp);
|
||||
}
|
||||
|
||||
public Runnable getRunnable()
|
||||
{
|
||||
return objectHolder.getFileWriter();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public enum RequestState
|
||||
{
|
||||
REQUEUE,
|
||||
SCHEDULE,
|
||||
FINISHED
|
||||
}
|
||||
}
|
@@ -54,7 +54,7 @@ public class User extends UserBase implements IUser
|
||||
private AtomicBoolean gotMailInfo = new AtomicBoolean(false);
|
||||
private WeakReference<Player> playerCache;
|
||||
|
||||
public User(final OfflinePlayer base, final IEssentials ess)
|
||||
public User(final OfflinePlayer base, final IEssentials ess) throws InvalidNameException
|
||||
{
|
||||
super(base, ess);
|
||||
teleport = new Teleport(this, ess);
|
||||
|
@@ -29,9 +29,9 @@ public abstract class UserBase extends AsyncStorageObjectHolder<UserData> implem
|
||||
@Delegate
|
||||
protected final OfflinePlayer offlinePlayer;
|
||||
|
||||
public UserBase(final OfflinePlayer base, final IEssentials ess)
|
||||
public UserBase(final OfflinePlayer base, final IEssentials ess) throws InvalidNameException
|
||||
{
|
||||
super(ess, UserData.class);
|
||||
super(ess, UserData.class, ess.getUserMap().getUserFile(base.getName()));
|
||||
this.offlinePlayer = base;
|
||||
onReload();
|
||||
}
|
||||
@@ -160,19 +160,6 @@ public abstract class UserBase extends AsyncStorageObjectHolder<UserData> implem
|
||||
throw new UnsupportedOperationException("Not supported yet.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public File getStorageFile() throws IOException
|
||||
{
|
||||
try
|
||||
{
|
||||
return ess.getUserMap().getUserFile(getName());
|
||||
}
|
||||
catch (InvalidNameException ex)
|
||||
{
|
||||
throw new IOException(ex.getMessage(), ex);
|
||||
}
|
||||
}
|
||||
|
||||
public long getTimestamp(final UserData.TimestampType name)
|
||||
{
|
||||
return getData().getTimestamp(name);
|
||||
|
@@ -90,12 +90,7 @@ public class UserMap extends StorageObjectMap<IUser> implements IUserMap
|
||||
@Override
|
||||
public IUser getUser(final Player player)
|
||||
{
|
||||
IUser user = getObject(player.getName());
|
||||
if (user == null)
|
||||
{
|
||||
user = new User(player, ess);
|
||||
}
|
||||
return user;
|
||||
return getObject(player.getName());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@@ -1,7 +1,6 @@
|
||||
package net.ess3.antibuild;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import net.ess3.api.IEssentials;
|
||||
import net.ess3.settings.antibuild.AntiBuild;
|
||||
import net.ess3.storage.AsyncStorageObjectHolder;
|
||||
@@ -10,13 +9,7 @@ public class AntiBuildHolder extends AsyncStorageObjectHolder<AntiBuild>
|
||||
{
|
||||
public AntiBuildHolder(final IEssentials ess)
|
||||
{
|
||||
super(ess, AntiBuild.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public File getStorageFile() throws IOException
|
||||
{
|
||||
return new File(ess.getPlugin().getDataFolder(), "protect.yml");
|
||||
super(ess, AntiBuild.class, new File(ess.getPlugin().getDataFolder(), "protect.yml"));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@@ -1,7 +1,6 @@
|
||||
package net.ess3.geoip;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import net.ess3.api.IEssentials;
|
||||
import net.ess3.settings.geoip.GeoIP;
|
||||
import net.ess3.storage.AsyncStorageObjectHolder;
|
||||
@@ -14,17 +13,11 @@ public class ConfigHolder extends AsyncStorageObjectHolder<GeoIP>
|
||||
|
||||
public ConfigHolder(final IEssentials ess, final Plugin geoip)
|
||||
{
|
||||
super(ess, GeoIP.class);
|
||||
super(ess, GeoIP.class, new File(geoip.getDataFolder(), "config.yml"));
|
||||
this.geoip = geoip;
|
||||
onReload(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public File getStorageFile() throws IOException
|
||||
{
|
||||
return new File(geoip.getDataFolder(), "config.yml");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void finishRead()
|
||||
{
|
||||
|
@@ -1,7 +1,6 @@
|
||||
package net.ess3.protect;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import net.ess3.api.IEssentials;
|
||||
import net.ess3.settings.protect.Protect;
|
||||
import net.ess3.storage.AsyncStorageObjectHolder;
|
||||
@@ -11,13 +10,7 @@ public class ProtectHolder extends AsyncStorageObjectHolder<Protect>
|
||||
{
|
||||
public ProtectHolder(final IEssentials ess)
|
||||
{
|
||||
super(ess, Protect.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public File getStorageFile() throws IOException
|
||||
{
|
||||
return new File(ess.getPlugin().getDataFolder(), "protect.yml");
|
||||
super(ess, Protect.class, new File(ess.getPlugin().getDataFolder(), "protect.yml"));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@@ -1,7 +1,6 @@
|
||||
package net.ess3.signs;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.*;
|
||||
import net.ess3.api.IEssentials;
|
||||
import net.ess3.storage.AsyncStorageObjectHolder;
|
||||
@@ -16,7 +15,7 @@ public class SignsConfigHolder extends AsyncStorageObjectHolder<SignsConfig>
|
||||
|
||||
public SignsConfigHolder(final IEssentials ess, final Plugin plugin)
|
||||
{
|
||||
super(ess, SignsConfig.class);
|
||||
super(ess, SignsConfig.class, new File(plugin.getDataFolder(), "config.yml"));
|
||||
this.plugin = plugin;
|
||||
onReload();
|
||||
final Map<String, Boolean> signs = getData().getSigns();
|
||||
@@ -44,12 +43,6 @@ public class SignsConfigHolder extends AsyncStorageObjectHolder<SignsConfig>
|
||||
queueSave();
|
||||
}
|
||||
|
||||
@Override
|
||||
public File getStorageFile() throws IOException
|
||||
{
|
||||
return new File(plugin.getDataFolder(), "config.yml");
|
||||
}
|
||||
|
||||
public Set<EssentialsSign> getEnabledSigns()
|
||||
{
|
||||
return enabledSigns;
|
||||
|
Reference in New Issue
Block a user