Refactoring storage - WIP. Towards #32
This commit is contained in:
parent
0d515abadb
commit
37fc00cce8
@ -49,6 +49,7 @@ import me.lucko.luckperms.common.storage.Datastore;
|
||||
import me.lucko.luckperms.common.storage.StorageFactory;
|
||||
import me.lucko.luckperms.common.tracks.TrackManager;
|
||||
import me.lucko.luckperms.common.users.UserManager;
|
||||
import me.lucko.luckperms.common.utils.BufferedRequest;
|
||||
import me.lucko.luckperms.common.utils.LocaleManager;
|
||||
import me.lucko.luckperms.common.utils.LogFactory;
|
||||
import org.bukkit.World;
|
||||
@ -84,6 +85,7 @@ public class LPBukkitPlugin extends JavaPlugin implements LuckPermsPlugin {
|
||||
private ContextManager<Player> contextManager;
|
||||
private WorldCalculator worldCalculator;
|
||||
private CalculatorFactory calculatorFactory;
|
||||
private BufferedRequest<Void> updateTaskBuffer;
|
||||
|
||||
@Override
|
||||
public void onEnable() {
|
||||
@ -139,10 +141,19 @@ public class LPBukkitPlugin extends JavaPlugin implements LuckPermsPlugin {
|
||||
contextManager.registerListener(new AutoOPListener());
|
||||
}
|
||||
|
||||
final LPBukkitPlugin i = this;
|
||||
updateTaskBuffer = new BufferedRequest<Void>(5000L, this::doAsync) {
|
||||
@Override
|
||||
protected Void perform() {
|
||||
getServer().getScheduler().runTaskAsynchronously(i, new UpdateTask(i));
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
int mins = getConfiguration().getSyncTime();
|
||||
if (mins > 0) {
|
||||
long ticks = mins * 60 * 20;
|
||||
getServer().getScheduler().runTaskTimerAsynchronously(this, new UpdateTask(this), ticks, ticks);
|
||||
getServer().getScheduler().runTaskTimerAsynchronously(this, () -> updateTaskBuffer.request(), ticks, ticks);
|
||||
}
|
||||
|
||||
getServer().getScheduler().runTaskTimer(this, BukkitSenderFactory.get(this), 1L, 1L);
|
||||
@ -188,7 +199,7 @@ public class LPBukkitPlugin extends JavaPlugin implements LuckPermsPlugin {
|
||||
@Override
|
||||
public void onDisable() {
|
||||
getLog().info("Closing datastore...");
|
||||
datastore.shutdown();
|
||||
datastore.shutdown().getOrDefault(null);
|
||||
|
||||
getLog().info("Unregistering API...");
|
||||
ApiHandler.unregisterProvider();
|
||||
@ -209,6 +220,11 @@ public class LPBukkitPlugin extends JavaPlugin implements LuckPermsPlugin {
|
||||
getServer().getScheduler().runTask(this, r);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doAsyncRepeating(Runnable r, long interval) {
|
||||
getServer().getScheduler().runTaskTimerAsynchronously(this, r, interval, interval);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getVersion() {
|
||||
return getDescription().getVersion();
|
||||
@ -347,11 +363,6 @@ public class LPBukkitPlugin extends JavaPlugin implements LuckPermsPlugin {
|
||||
return getServer().getPluginManager().isPluginEnabled(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void runUpdateTask() {
|
||||
getServer().getScheduler().runTaskAsynchronously(this, new UpdateTask(this));
|
||||
}
|
||||
|
||||
private void registerPermissions(PermissionDefault def) {
|
||||
PluginManager pm = getServer().getPluginManager();
|
||||
|
||||
|
@ -95,7 +95,7 @@ public class BungeeListener extends AbstractListener implements Listener {
|
||||
final PendingConnection c = e.getConnection();
|
||||
|
||||
if (!cache.isOnlineMode()) {
|
||||
UUID uuid = plugin.getDatastore().getUUID(c.getName());
|
||||
UUID uuid = plugin.getDatastore().getUUID(c.getName()).getOrDefault(null);
|
||||
if (uuid != null) {
|
||||
cache.addToCache(c.getUniqueId(), uuid);
|
||||
} else {
|
||||
@ -105,7 +105,7 @@ public class BungeeListener extends AbstractListener implements Listener {
|
||||
plugin.getDatastore().saveUUIDData(c.getName(), c.getUniqueId());
|
||||
}
|
||||
} else {
|
||||
UUID uuid = plugin.getDatastore().getUUID(c.getName());
|
||||
UUID uuid = plugin.getDatastore().getUUID(c.getName()).getOrDefault(null);
|
||||
if (uuid == null) {
|
||||
plugin.getApiProvider().fireEventAsync(new UserFirstLoginEvent(c.getUniqueId(), c.getName()));
|
||||
}
|
||||
|
@ -268,4 +268,10 @@ public class LPBungeePlugin extends Plugin implements LuckPermsPlugin {
|
||||
public void doSync(Runnable r) {
|
||||
r.run();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doAsyncRepeating(Runnable r, long interval) {
|
||||
long millis = interval * 50L; // convert from ticks to milliseconds
|
||||
getProxy().getScheduler().schedule(this, r, millis, millis, TimeUnit.MILLISECONDS);
|
||||
}
|
||||
}
|
||||
|
@ -38,6 +38,7 @@ import me.lucko.luckperms.common.groups.GroupManager;
|
||||
import me.lucko.luckperms.common.storage.Datastore;
|
||||
import me.lucko.luckperms.common.tracks.TrackManager;
|
||||
import me.lucko.luckperms.common.users.UserManager;
|
||||
import me.lucko.luckperms.common.utils.BufferedRequest;
|
||||
import me.lucko.luckperms.common.utils.LocaleManager;
|
||||
|
||||
import java.io.File;
|
||||
@ -177,7 +178,7 @@ public interface LuckPermsPlugin {
|
||||
/**
|
||||
* Runs an update task
|
||||
*/
|
||||
void runUpdateTask();
|
||||
BufferedRequest<Void> getUpdateTaskBuffer();
|
||||
|
||||
/**
|
||||
* Execute a runnable asynchronously
|
||||
@ -191,4 +192,11 @@ public interface LuckPermsPlugin {
|
||||
*/
|
||||
void doSync(Runnable r);
|
||||
|
||||
/**
|
||||
* Execute a runnable asynchronously on a loop
|
||||
* @param r the task to run
|
||||
* @param interval the time between runs in ticks
|
||||
*/
|
||||
void doAsyncRepeating(Runnable r, long interval);
|
||||
|
||||
}
|
||||
|
@ -22,19 +22,15 @@
|
||||
|
||||
package me.lucko.luckperms.common.api.internal;
|
||||
|
||||
import lombok.AccessLevel;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.NonNull;
|
||||
import me.lucko.luckperms.api.*;
|
||||
import me.lucko.luckperms.api.data.Callback;
|
||||
import me.lucko.luckperms.common.LuckPermsPlugin;
|
||||
import me.lucko.luckperms.common.storage.AbstractFuture;
|
||||
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
|
||||
import static me.lucko.luckperms.common.api.internal.Utils.*;
|
||||
|
||||
@ -210,64 +206,68 @@ public class DatastoreLink implements Datastore {
|
||||
|
||||
@Override
|
||||
public boolean logAction(@NonNull LogEntry entry) {
|
||||
return master.logAction(entry);
|
||||
return master.logAction(entry).getOrDefault(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Log getLog() {
|
||||
return new LogLink(master.getLog());
|
||||
me.lucko.luckperms.common.data.Log log = master.getLog().getOrDefault(null);
|
||||
if (log == null) {
|
||||
return null;
|
||||
}
|
||||
return new LogLink(log);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean loadOrCreateUser(@NonNull UUID uuid, @NonNull String username) {
|
||||
return master.loadUser(uuid, checkUsername(username));
|
||||
return master.loadUser(uuid, checkUsername(username)).getOrDefault(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean loadUser(@NonNull UUID uuid) {
|
||||
return master.loadUser(uuid, "null");
|
||||
return master.loadUser(uuid, "null").getOrDefault(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean loadUser(@NonNull UUID uuid, @NonNull String username) {
|
||||
return master.loadUser(uuid, checkUsername(username));
|
||||
return master.loadUser(uuid, checkUsername(username)).getOrDefault(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean saveUser(@NonNull User user) {
|
||||
checkUser(user);
|
||||
return master.saveUser(((UserLink) user).getMaster());
|
||||
return master.saveUser(((UserLink) user).getMaster()).getOrDefault(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean cleanupUsers() {
|
||||
return master.cleanupUsers();
|
||||
return master.cleanupUsers().getOrDefault(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<UUID> getUniqueUsers() {
|
||||
return master.getUniqueUsers();
|
||||
return master.getUniqueUsers().getOrDefault(null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean createAndLoadGroup(@NonNull String name) {
|
||||
return master.createAndLoadGroup(checkName(name));
|
||||
return master.createAndLoadGroup(checkName(name)).getOrDefault(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean loadGroup(@NonNull String name) {
|
||||
return master.loadGroup(checkName(name));
|
||||
return master.loadGroup(checkName(name)).getOrDefault(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean loadAllGroups() {
|
||||
return master.loadAllGroups();
|
||||
return master.loadAllGroups().getOrDefault(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean saveGroup(@NonNull Group group) {
|
||||
checkGroup(group);
|
||||
return master.saveGroup(((GroupLink) group).getMaster());
|
||||
return master.saveGroup(((GroupLink) group).getMaster()).getOrDefault(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -276,44 +276,44 @@ public class DatastoreLink implements Datastore {
|
||||
if (group.getName().equalsIgnoreCase(plugin.getConfiguration().getDefaultGroupName())) {
|
||||
throw new IllegalArgumentException("Cannot delete the default group.");
|
||||
}
|
||||
return master.deleteGroup(((GroupLink) group).getMaster());
|
||||
return master.deleteGroup(((GroupLink) group).getMaster()).getOrDefault(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean createAndLoadTrack(@NonNull String name) {
|
||||
return master.createAndLoadTrack(checkName(name));
|
||||
return master.createAndLoadTrack(checkName(name)).getOrDefault(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean loadTrack(@NonNull String name) {
|
||||
return master.loadTrack(checkName(name));
|
||||
return master.loadTrack(checkName(name)).getOrDefault(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean loadAllTracks() {
|
||||
return master.loadAllTracks();
|
||||
return master.loadAllTracks().getOrDefault(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean saveTrack(@NonNull Track track) {
|
||||
checkTrack(track);
|
||||
return master.saveTrack(((TrackLink) track).getMaster());
|
||||
return master.saveTrack(((TrackLink) track).getMaster()).getOrDefault(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean deleteTrack(@NonNull Track track) {
|
||||
checkTrack(track);
|
||||
return master.deleteTrack(((TrackLink) track).getMaster());
|
||||
return master.deleteTrack(((TrackLink) track).getMaster()).getOrDefault(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean saveUUIDData(@NonNull String username, @NonNull UUID uuid) {
|
||||
return master.saveUUIDData(checkUsername(username), uuid);
|
||||
return master.saveUUIDData(checkUsername(username), uuid).getOrDefault(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public UUID getUUID(@NonNull String username) {
|
||||
return master.getUUID(checkUsername(username));
|
||||
return master.getUUID(checkUsername(username)).getOrDefault(null);
|
||||
}
|
||||
}
|
||||
|
||||
@ -323,193 +323,112 @@ public class DatastoreLink implements Datastore {
|
||||
|
||||
@Override
|
||||
public java.util.concurrent.Future<Boolean> logAction(@NonNull LogEntry entry) {
|
||||
LPFuture<Boolean> lpf = new LPFuture<>();
|
||||
master.logAction(entry, lpf);
|
||||
return lpf;
|
||||
return master.logAction(entry);
|
||||
}
|
||||
|
||||
@Override
|
||||
public java.util.concurrent.Future<Log> getLog() {
|
||||
LPFuture<Log> lpf = new LPFuture<>();
|
||||
master.getLog(log -> lpf.onComplete(new LogLink(log)));
|
||||
return lpf;
|
||||
AbstractFuture<Log> fut = new AbstractFuture<>();
|
||||
master.getLog(log -> fut.complete(new LogLink(log)));
|
||||
return fut;
|
||||
}
|
||||
|
||||
@Override
|
||||
public java.util.concurrent.Future<Boolean> loadOrCreateUser(@NonNull UUID uuid, @NonNull String username) {
|
||||
LPFuture<Boolean> lpf = new LPFuture<>();
|
||||
master.loadUser(uuid, checkUsername(username), lpf);
|
||||
return lpf;
|
||||
return master.loadUser(uuid, checkUsername(username));
|
||||
}
|
||||
|
||||
@Override
|
||||
public java.util.concurrent.Future<Boolean> loadUser(@NonNull UUID uuid) {
|
||||
LPFuture<Boolean> lpf = new LPFuture<>();
|
||||
master.loadUser(uuid, "null", lpf);
|
||||
return lpf;
|
||||
return master.loadUser(uuid, "null");
|
||||
}
|
||||
|
||||
@Override
|
||||
public java.util.concurrent.Future<Boolean> loadUser(@NonNull UUID uuid, @NonNull String username) {
|
||||
LPFuture<Boolean> lpf = new LPFuture<>();
|
||||
master.loadUser(uuid, checkUsername(username), lpf);
|
||||
return lpf;
|
||||
return master.loadUser(uuid, checkUsername(username));
|
||||
}
|
||||
|
||||
@Override
|
||||
public java.util.concurrent.Future<Boolean> saveUser(@NonNull User user) {
|
||||
LPFuture<Boolean> lpf = new LPFuture<>();
|
||||
checkUser(user);
|
||||
master.saveUser(((UserLink) user).getMaster(), lpf);
|
||||
return lpf;
|
||||
return master.saveUser(((UserLink) user).getMaster());
|
||||
}
|
||||
|
||||
@Override
|
||||
public java.util.concurrent.Future<Boolean> cleanupUsers() {
|
||||
LPFuture<Boolean> lpf = new LPFuture<>();
|
||||
master.cleanupUsers(lpf);
|
||||
return lpf;
|
||||
return master.cleanupUsers();
|
||||
}
|
||||
|
||||
@Override
|
||||
public java.util.concurrent.Future<Set<UUID>> getUniqueUsers() {
|
||||
LPFuture<Set<UUID>> lpf = new LPFuture<>();
|
||||
master.getUniqueUsers(lpf);
|
||||
return lpf;
|
||||
return master.getUniqueUsers();
|
||||
}
|
||||
|
||||
@Override
|
||||
public java.util.concurrent.Future<Boolean> createAndLoadGroup(@NonNull String name) {
|
||||
LPFuture<Boolean> lpf = new LPFuture<>();
|
||||
master.createAndLoadGroup(checkName(name), lpf);
|
||||
return lpf;
|
||||
return master.createAndLoadGroup(checkName(name));
|
||||
}
|
||||
|
||||
@Override
|
||||
public java.util.concurrent.Future<Boolean> loadGroup(@NonNull String name) {
|
||||
LPFuture<Boolean> lpf = new LPFuture<>();
|
||||
master.loadGroup(checkName(name), lpf);
|
||||
return lpf;
|
||||
return master.loadGroup(checkName(name));
|
||||
}
|
||||
|
||||
@Override
|
||||
public java.util.concurrent.Future<Boolean> loadAllGroups() {
|
||||
LPFuture<Boolean> lpf = new LPFuture<>();
|
||||
master.loadAllGroups(lpf);
|
||||
return lpf;
|
||||
return master.loadAllGroups();
|
||||
}
|
||||
|
||||
@Override
|
||||
public java.util.concurrent.Future<Boolean> saveGroup(@NonNull Group group) {
|
||||
LPFuture<Boolean> lpf = new LPFuture<>();
|
||||
checkGroup(group);
|
||||
master.saveGroup(((GroupLink) group).getMaster(), lpf);
|
||||
return lpf;
|
||||
return master.saveGroup(((GroupLink) group).getMaster());
|
||||
}
|
||||
|
||||
@Override
|
||||
public java.util.concurrent.Future<Boolean> deleteGroup(@NonNull Group group) {
|
||||
LPFuture<Boolean> lpf = new LPFuture<>();
|
||||
checkGroup(group);
|
||||
if (group.getName().equalsIgnoreCase(plugin.getConfiguration().getDefaultGroupName())) {
|
||||
throw new IllegalArgumentException("Cannot delete the default group.");
|
||||
}
|
||||
master.deleteGroup(((GroupLink) group).getMaster(), lpf);
|
||||
return lpf;
|
||||
return master.deleteGroup(((GroupLink) group).getMaster());
|
||||
}
|
||||
|
||||
@Override
|
||||
public java.util.concurrent.Future<Boolean> createAndLoadTrack(@NonNull String name) {
|
||||
LPFuture<Boolean> lpf = new LPFuture<>();
|
||||
master.createAndLoadTrack(checkName(name), lpf);
|
||||
return lpf;
|
||||
return master.createAndLoadTrack(checkName(name));
|
||||
}
|
||||
|
||||
@Override
|
||||
public java.util.concurrent.Future<Boolean> loadTrack(@NonNull String name) {
|
||||
LPFuture<Boolean> lpf = new LPFuture<>();
|
||||
master.loadTrack(checkName(name), lpf);
|
||||
return lpf;
|
||||
return master.loadTrack(checkName(name));
|
||||
}
|
||||
|
||||
@Override
|
||||
public java.util.concurrent.Future<Boolean> loadAllTracks() {
|
||||
LPFuture<Boolean> lpf = new LPFuture<>();
|
||||
master.loadAllTracks(lpf);
|
||||
return lpf;
|
||||
return master.loadAllTracks();
|
||||
}
|
||||
|
||||
@Override
|
||||
public java.util.concurrent.Future<Boolean> saveTrack(@NonNull Track track) {
|
||||
LPFuture<Boolean> lpf = new LPFuture<>();
|
||||
checkTrack(track);
|
||||
master.saveTrack(((TrackLink) track).getMaster(), lpf);
|
||||
return lpf;
|
||||
return master.saveTrack(((TrackLink) track).getMaster());
|
||||
}
|
||||
|
||||
@Override
|
||||
public java.util.concurrent.Future<Boolean> deleteTrack(@NonNull Track track) {
|
||||
LPFuture<Boolean> lpf = new LPFuture<>();
|
||||
checkTrack(track);
|
||||
master.deleteTrack(((TrackLink) track).getMaster(), lpf);
|
||||
return lpf;
|
||||
return master.deleteTrack(((TrackLink) track).getMaster());
|
||||
}
|
||||
|
||||
@Override
|
||||
public java.util.concurrent.Future<Boolean> saveUUIDData(@NonNull String username, @NonNull UUID uuid) {
|
||||
LPFuture<Boolean> lpf = new LPFuture<>();
|
||||
master.saveUUIDData(checkUsername(username), uuid, lpf);
|
||||
return lpf;
|
||||
return master.saveUUIDData(checkUsername(username), uuid);
|
||||
}
|
||||
|
||||
@Override
|
||||
public java.util.concurrent.Future<UUID> getUUID(@NonNull String username) {
|
||||
LPFuture<UUID> lpf = new LPFuture<>();
|
||||
master.getUUID(checkUsername(username), lpf);
|
||||
return lpf;
|
||||
}
|
||||
}
|
||||
|
||||
@NoArgsConstructor(access = AccessLevel.PRIVATE)
|
||||
public static class LPFuture<T> implements Callback<T>, java.util.concurrent.Future<T> {
|
||||
private final CountDownLatch latch = new CountDownLatch(1);
|
||||
private T value;
|
||||
|
||||
@Override
|
||||
public void onComplete(T t) {
|
||||
value = t;
|
||||
latch.countDown();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean cancel(boolean mayInterruptIfRunning) {
|
||||
// Not supported
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCancelled() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDone() {
|
||||
return latch.getCount() == 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public T get() throws InterruptedException {
|
||||
latch.await();
|
||||
return value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public T get(long timeout, TimeUnit unit) throws InterruptedException, TimeoutException {
|
||||
if (latch.await(timeout, unit)) {
|
||||
return value;
|
||||
} else {
|
||||
throw new TimeoutException();
|
||||
}
|
||||
return master.getUUID(checkUsername(username));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -162,7 +162,7 @@ public abstract class SubCommand<T> {
|
||||
}
|
||||
|
||||
public static void save(User user, Sender sender, LuckPermsPlugin plugin) {
|
||||
if (plugin.getDatastore().saveUser(user)) {
|
||||
if (plugin.getDatastore().saveUser(user).getOrDefault(false)) {
|
||||
Message.USER_SAVE_SUCCESS.send(sender);
|
||||
} else {
|
||||
Message.USER_SAVE_ERROR.send(sender);
|
||||
@ -172,7 +172,7 @@ public abstract class SubCommand<T> {
|
||||
}
|
||||
|
||||
public static void save(Group group, Sender sender, LuckPermsPlugin plugin) {
|
||||
if (plugin.getDatastore().saveGroup(group)) {
|
||||
if (plugin.getDatastore().saveGroup(group).getOrDefault(false)) {
|
||||
Message.GROUP_SAVE_SUCCESS.send(sender);
|
||||
} else {
|
||||
Message.GROUP_SAVE_ERROR.send(sender);
|
||||
@ -182,7 +182,7 @@ public abstract class SubCommand<T> {
|
||||
}
|
||||
|
||||
public static void save(Track track, Sender sender, LuckPermsPlugin plugin) {
|
||||
if (plugin.getDatastore().saveTrack(track)) {
|
||||
if (plugin.getDatastore().saveTrack(track).getOrDefault(false)) {
|
||||
Message.TRACK_SAVE_SUCCESS.send(sender);
|
||||
} else {
|
||||
Message.TRACK_SAVE_ERROR.send(sender);
|
||||
|
@ -61,7 +61,7 @@ public class ParentAdd extends SecondarySubCommand {
|
||||
return CommandResult.INVALID_ARGS;
|
||||
}
|
||||
|
||||
if (!plugin.getDatastore().loadGroup(groupName)) {
|
||||
if (!plugin.getDatastore().loadGroup(groupName).getOrDefault(false)) {
|
||||
Message.GROUP_DOES_NOT_EXIST.send(sender);
|
||||
return CommandResult.INVALID_ARGS;
|
||||
}
|
||||
|
@ -80,7 +80,7 @@ public class ParentAddTemp extends SecondarySubCommand {
|
||||
return CommandResult.INVALID_ARGS;
|
||||
}
|
||||
|
||||
if (!plugin.getDatastore().loadGroup(groupName)) {
|
||||
if (!plugin.getDatastore().loadGroup(groupName).getOrDefault(false)) {
|
||||
Message.GROUP_DOES_NOT_EXIST.send(sender);
|
||||
return CommandResult.INVALID_ARGS;
|
||||
}
|
||||
|
@ -51,12 +51,12 @@ public class CreateGroup extends SingleMainCommand {
|
||||
return CommandResult.INVALID_ARGS;
|
||||
}
|
||||
|
||||
if (plugin.getDatastore().loadGroup(groupName)) {
|
||||
if (plugin.getDatastore().loadGroup(groupName).getOrDefault(false)) {
|
||||
Message.GROUP_ALREADY_EXISTS.send(sender);
|
||||
return CommandResult.INVALID_ARGS;
|
||||
}
|
||||
|
||||
if (!plugin.getDatastore().createAndLoadGroup(groupName)) {
|
||||
if (!plugin.getDatastore().createAndLoadGroup(groupName).getOrDefault(false)) {
|
||||
Message.CREATE_GROUP_ERROR.send(sender);
|
||||
return CommandResult.FAILURE;
|
||||
}
|
||||
|
@ -55,7 +55,7 @@ public class DeleteGroup extends SingleMainCommand {
|
||||
return CommandResult.INVALID_ARGS;
|
||||
}
|
||||
|
||||
if (!plugin.getDatastore().loadGroup(groupName)) {
|
||||
if (!plugin.getDatastore().loadGroup(groupName).getOrDefault(false)) {
|
||||
Message.GROUP_DOES_NOT_EXIST.send(sender);
|
||||
return CommandResult.INVALID_ARGS;
|
||||
}
|
||||
@ -66,7 +66,7 @@ public class DeleteGroup extends SingleMainCommand {
|
||||
return CommandResult.LOADING_ERROR;
|
||||
}
|
||||
|
||||
if (!plugin.getDatastore().deleteGroup(group)) {
|
||||
if (!plugin.getDatastore().deleteGroup(group).getOrDefault(false)) {
|
||||
Message.DELETE_GROUP_ERROR.send(sender);
|
||||
return CommandResult.FAILURE;
|
||||
}
|
||||
|
@ -57,7 +57,7 @@ public class GroupMainCommand extends MainCommand<Group> {
|
||||
|
||||
@Override
|
||||
protected Group getTarget(String target, LuckPermsPlugin plugin, Sender sender) {
|
||||
if (!plugin.getDatastore().loadGroup(target)) {
|
||||
if (!plugin.getDatastore().loadGroup(target).getOrDefault(false)) {
|
||||
Message.GROUP_NOT_FOUND.send(sender);
|
||||
return null;
|
||||
}
|
||||
|
@ -42,7 +42,7 @@ public class ListGroups extends SingleMainCommand {
|
||||
|
||||
@Override
|
||||
protected CommandResult execute(LuckPermsPlugin plugin, Sender sender, List<String> args, String label) {
|
||||
if (!plugin.getDatastore().loadAllGroups()) {
|
||||
if (!plugin.getDatastore().loadAllGroups().getOrDefault(false)) {
|
||||
Message.GROUPS_LOAD_ERROR.send(sender);
|
||||
return CommandResult.LOADING_ERROR;
|
||||
}
|
||||
|
@ -47,12 +47,12 @@ public class GroupClone extends SubCommand<Group> {
|
||||
return CommandResult.INVALID_ARGS;
|
||||
}
|
||||
|
||||
if (plugin.getDatastore().loadGroup(newGroupName)) {
|
||||
if (plugin.getDatastore().loadGroup(newGroupName).getOrDefault(false)) {
|
||||
Message.GROUP_ALREADY_EXISTS.send(sender);
|
||||
return CommandResult.INVALID_ARGS;
|
||||
}
|
||||
|
||||
if (!plugin.getDatastore().createAndLoadGroup(newGroupName)) {
|
||||
if (!plugin.getDatastore().createAndLoadGroup(newGroupName).getOrDefault(false)) {
|
||||
Message.CREATE_GROUP_ERROR.send(sender);
|
||||
return CommandResult.FAILURE;
|
||||
}
|
||||
|
@ -47,12 +47,12 @@ public class GroupRename extends SubCommand<Group> {
|
||||
return CommandResult.INVALID_ARGS;
|
||||
}
|
||||
|
||||
if (plugin.getDatastore().loadGroup(newGroupName)) {
|
||||
if (plugin.getDatastore().loadGroup(newGroupName).getOrDefault(false)) {
|
||||
Message.GROUP_ALREADY_EXISTS.send(sender);
|
||||
return CommandResult.INVALID_ARGS;
|
||||
}
|
||||
|
||||
if (!plugin.getDatastore().createAndLoadGroup(newGroupName)) {
|
||||
if (!plugin.getDatastore().createAndLoadGroup(newGroupName).getOrDefault(false)) {
|
||||
Message.CREATE_GROUP_ERROR.send(sender);
|
||||
return CommandResult.FAILURE;
|
||||
}
|
||||
@ -63,7 +63,7 @@ public class GroupRename extends SubCommand<Group> {
|
||||
return CommandResult.LOADING_ERROR;
|
||||
}
|
||||
|
||||
if (!plugin.getDatastore().deleteGroup(group)) {
|
||||
if (!plugin.getDatastore().deleteGroup(group).getOrDefault(false)) {
|
||||
Message.DELETE_GROUP_ERROR.send(sender);
|
||||
return CommandResult.FAILURE;
|
||||
}
|
||||
|
@ -39,7 +39,7 @@ public class GroupShowTracks extends SubCommand<Group> {
|
||||
|
||||
@Override
|
||||
public CommandResult execute(LuckPermsPlugin plugin, Sender sender, Group group, List<String> args, String label) {
|
||||
if (!plugin.getDatastore().loadAllTracks()) {
|
||||
if (!plugin.getDatastore().loadAllTracks().getOrDefault(false)) {
|
||||
Message.TRACKS_LOAD_ERROR.send(sender);
|
||||
return CommandResult.LOADING_ERROR;
|
||||
}
|
||||
|
@ -52,7 +52,7 @@ public class LogMainCommand extends MainCommand<Log> {
|
||||
|
||||
@Override
|
||||
protected Log getTarget(String target, LuckPermsPlugin plugin, Sender sender) {
|
||||
Log log = plugin.getDatastore().getLog();
|
||||
Log log = plugin.getDatastore().getLog().getOrDefault(null);
|
||||
|
||||
if (log == null) {
|
||||
Message.LOG_LOAD_ERROR.send(sender);
|
||||
|
@ -74,7 +74,7 @@ public class LogRecent extends SubCommand<Log> {
|
||||
return CommandResult.INVALID_ARGS;
|
||||
}
|
||||
|
||||
UUID uuid = plugin.getDatastore().getUUID(s);
|
||||
UUID uuid = plugin.getDatastore().getUUID(s).getOrDefault(null);
|
||||
|
||||
if (uuid == null) {
|
||||
Message.USER_NOT_FOUND.send(sender);
|
||||
|
@ -76,7 +76,7 @@ public class LogUserHistory extends SubCommand<Log> {
|
||||
return CommandResult.INVALID_ARGS;
|
||||
}
|
||||
|
||||
UUID uuid1 = plugin.getDatastore().getUUID(user);
|
||||
UUID uuid1 = plugin.getDatastore().getUUID(user).getOrDefault(null);
|
||||
|
||||
if (uuid1 == null) {
|
||||
Message.USER_NOT_FOUND.send(sender);
|
||||
|
@ -118,7 +118,7 @@ public class ExportCommand extends SingleMainCommand {
|
||||
// Export users
|
||||
log.info("Export: Exporting all users. Finding a list of unique users to export.");
|
||||
Datastore ds = plugin.getDatastore();
|
||||
Set<UUID> users = ds.getUniqueUsers();
|
||||
Set<UUID> users = ds.getUniqueUsers().getOrDefault(null);
|
||||
log.info("Export: Found " + users.size() + " unique users to export.");
|
||||
|
||||
int userCount = 0;
|
||||
|
@ -51,12 +51,12 @@ public class CreateTrack extends SingleMainCommand {
|
||||
return CommandResult.INVALID_ARGS;
|
||||
}
|
||||
|
||||
if (plugin.getDatastore().loadTrack(trackName)) {
|
||||
if (plugin.getDatastore().loadTrack(trackName).getOrDefault(false)) {
|
||||
Message.TRACK_ALREADY_EXISTS.send(sender);
|
||||
return CommandResult.INVALID_ARGS;
|
||||
}
|
||||
|
||||
if (!plugin.getDatastore().createAndLoadTrack(trackName)) {
|
||||
if (!plugin.getDatastore().createAndLoadTrack(trackName).getOrDefault(false)) {
|
||||
Message.CREATE_TRACK_ERROR.send(sender);
|
||||
return CommandResult.FAILURE;
|
||||
}
|
||||
|
@ -49,7 +49,7 @@ public class DeleteTrack extends SingleMainCommand {
|
||||
}
|
||||
|
||||
String trackName = args.get(0).toLowerCase();
|
||||
if (!plugin.getDatastore().loadTrack(trackName)) {
|
||||
if (!plugin.getDatastore().loadTrack(trackName).getOrDefault(false)) {
|
||||
Message.TRACK_DOES_NOT_EXIST.send(sender);
|
||||
return CommandResult.INVALID_ARGS;
|
||||
}
|
||||
@ -60,7 +60,7 @@ public class DeleteTrack extends SingleMainCommand {
|
||||
return CommandResult.LOADING_ERROR;
|
||||
}
|
||||
|
||||
if (!plugin.getDatastore().deleteTrack(track)) {
|
||||
if (!plugin.getDatastore().deleteTrack(track).getOrDefault(false)) {
|
||||
Message.DELETE_TRACK_ERROR.send(sender);
|
||||
return CommandResult.FAILURE;
|
||||
}
|
||||
|
@ -40,7 +40,7 @@ public class ListTracks extends SingleMainCommand {
|
||||
|
||||
@Override
|
||||
protected CommandResult execute(LuckPermsPlugin plugin, Sender sender, List<String> args, String label) {
|
||||
if (!plugin.getDatastore().loadAllTracks()) {
|
||||
if (!plugin.getDatastore().loadAllTracks().getOrDefault(false)) {
|
||||
Message.TRACKS_LOAD_ERROR.send(sender);
|
||||
return CommandResult.LOADING_ERROR;
|
||||
}
|
||||
|
@ -50,7 +50,7 @@ public class TrackMainCommand extends MainCommand<Track> {
|
||||
|
||||
@Override
|
||||
protected Track getTarget(String target, LuckPermsPlugin plugin, Sender sender) {
|
||||
if (!plugin.getDatastore().loadTrack(target)) {
|
||||
if (!plugin.getDatastore().loadTrack(target).getOrDefault(false)) {
|
||||
Message.TRACK_NOT_FOUND.send(sender);
|
||||
return null;
|
||||
}
|
||||
|
@ -50,7 +50,7 @@ public class TrackAppend extends SubCommand<Track> {
|
||||
return CommandResult.INVALID_ARGS;
|
||||
}
|
||||
|
||||
if (!plugin.getDatastore().loadGroup(groupName)) {
|
||||
if (!plugin.getDatastore().loadGroup(groupName).getOrDefault(false)) {
|
||||
Message.GROUP_DOES_NOT_EXIST.send(sender);
|
||||
return CommandResult.INVALID_ARGS;
|
||||
}
|
||||
|
@ -47,12 +47,12 @@ public class TrackClone extends SubCommand<Track> {
|
||||
return CommandResult.INVALID_ARGS;
|
||||
}
|
||||
|
||||
if (plugin.getDatastore().loadTrack(newTrackName)) {
|
||||
if (plugin.getDatastore().loadTrack(newTrackName).getOrDefault(false)) {
|
||||
Message.TRACK_ALREADY_EXISTS.send(sender);
|
||||
return CommandResult.INVALID_ARGS;
|
||||
}
|
||||
|
||||
if (!plugin.getDatastore().createAndLoadTrack(newTrackName)) {
|
||||
if (!plugin.getDatastore().createAndLoadTrack(newTrackName).getOrDefault(false)) {
|
||||
Message.CREATE_TRACK_ERROR.send(sender);
|
||||
return CommandResult.FAILURE;
|
||||
}
|
||||
|
@ -61,7 +61,7 @@ public class TrackInsert extends SubCommand<Track> {
|
||||
return CommandResult.INVALID_ARGS;
|
||||
}
|
||||
|
||||
if (!plugin.getDatastore().loadGroup(groupName)) {
|
||||
if (!plugin.getDatastore().loadGroup(groupName).getOrDefault(false)) {
|
||||
Message.GROUP_DOES_NOT_EXIST.send(sender);
|
||||
return CommandResult.INVALID_ARGS;
|
||||
}
|
||||
|
@ -47,12 +47,12 @@ public class TrackRename extends SubCommand<Track> {
|
||||
return CommandResult.INVALID_ARGS;
|
||||
}
|
||||
|
||||
if (plugin.getDatastore().loadTrack(newTrackName)) {
|
||||
if (plugin.getDatastore().loadTrack(newTrackName).getOrDefault(false)) {
|
||||
Message.TRACK_ALREADY_EXISTS.send(sender);
|
||||
return CommandResult.INVALID_ARGS;
|
||||
}
|
||||
|
||||
if (!plugin.getDatastore().createAndLoadTrack(newTrackName)) {
|
||||
if (!plugin.getDatastore().createAndLoadTrack(newTrackName).getOrDefault(false)) {
|
||||
Message.CREATE_TRACK_ERROR.send(sender);
|
||||
return CommandResult.FAILURE;
|
||||
}
|
||||
@ -63,7 +63,7 @@ public class TrackRename extends SubCommand<Track> {
|
||||
return CommandResult.LOADING_ERROR;
|
||||
}
|
||||
|
||||
if (!plugin.getDatastore().deleteTrack(track)) {
|
||||
if (!plugin.getDatastore().deleteTrack(track).getOrDefault(false)) {
|
||||
Message.DELETE_TRACK_ERROR.send(sender);
|
||||
return CommandResult.FAILURE;
|
||||
}
|
||||
|
@ -70,7 +70,7 @@ public class UserMainCommand extends MainCommand<User> {
|
||||
return null;
|
||||
}
|
||||
|
||||
u = plugin.getDatastore().getUUID(target);
|
||||
u = plugin.getDatastore().getUUID(target).getOrDefault(null);
|
||||
if (u == null) {
|
||||
Message.USER_NOT_FOUND.send(sender);
|
||||
return null;
|
||||
@ -80,10 +80,10 @@ public class UserMainCommand extends MainCommand<User> {
|
||||
}
|
||||
}
|
||||
|
||||
String name = plugin.getDatastore().getName(u);
|
||||
String name = plugin.getDatastore().getName(u).getOrDefault(null);
|
||||
if (name == null) name = "null";
|
||||
|
||||
if (!plugin.getDatastore().loadUser(u, name)) {
|
||||
if (!plugin.getDatastore().loadUser(u, name).getOrDefault(false)) {
|
||||
Message.LOADING_ERROR.send(sender);
|
||||
}
|
||||
|
||||
|
@ -54,7 +54,7 @@ public class UserDemote extends SubCommand<User> {
|
||||
return CommandResult.INVALID_ARGS;
|
||||
}
|
||||
|
||||
if (!plugin.getDatastore().loadTrack(trackName)) {
|
||||
if (!plugin.getDatastore().loadTrack(trackName).getOrDefault(false)) {
|
||||
Message.TRACK_DOES_NOT_EXIST.send(sender);
|
||||
return CommandResult.INVALID_ARGS;
|
||||
}
|
||||
@ -85,7 +85,7 @@ public class UserDemote extends SubCommand<User> {
|
||||
return CommandResult.STATE_ERROR;
|
||||
}
|
||||
|
||||
if (!plugin.getDatastore().loadGroup(previous)) {
|
||||
if (!plugin.getDatastore().loadGroup(previous).getOrDefault(false)) {
|
||||
Message.USER_DEMOTE_ERROR_MALFORMED.send(sender, previous);
|
||||
return CommandResult.STATE_ERROR;
|
||||
}
|
||||
|
@ -54,7 +54,7 @@ public class UserPromote extends SubCommand<User> {
|
||||
return CommandResult.INVALID_ARGS;
|
||||
}
|
||||
|
||||
if (!plugin.getDatastore().loadTrack(trackName)) {
|
||||
if (!plugin.getDatastore().loadTrack(trackName).getOrDefault(false)) {
|
||||
Message.TRACK_DOES_NOT_EXIST.send(sender);
|
||||
return CommandResult.INVALID_ARGS;
|
||||
}
|
||||
@ -85,7 +85,7 @@ public class UserPromote extends SubCommand<User> {
|
||||
return CommandResult.STATE_ERROR;
|
||||
}
|
||||
|
||||
if (!plugin.getDatastore().loadGroup(next)) {
|
||||
if (!plugin.getDatastore().loadGroup(next).getOrDefault(false)) {
|
||||
Message.USER_PROMOTE_ERROR_MALFORMED.send(sender, next);
|
||||
return CommandResult.STATE_ERROR;
|
||||
}
|
||||
|
@ -47,7 +47,7 @@ public class UserShowPos extends SubCommand<User> {
|
||||
return CommandResult.INVALID_ARGS;
|
||||
}
|
||||
|
||||
if (!plugin.getDatastore().loadTrack(trackName)) {
|
||||
if (!plugin.getDatastore().loadTrack(trackName).getOrDefault(false)) {
|
||||
Message.TRACK_DOES_NOT_EXIST.send(sender);
|
||||
return CommandResult.INVALID_ARGS;
|
||||
}
|
||||
|
@ -40,7 +40,7 @@ public class UserShowTracks extends SubCommand<User> {
|
||||
|
||||
@Override
|
||||
public CommandResult execute(LuckPermsPlugin plugin, Sender sender, User user, List<String> args, String label) {
|
||||
if (!plugin.getDatastore().loadAllTracks()) {
|
||||
if (!plugin.getDatastore().loadAllTracks().getOrDefault(false)) {
|
||||
Message.TRACKS_LOAD_ERROR.send(sender);
|
||||
return CommandResult.LOADING_ERROR;
|
||||
}
|
||||
|
@ -61,7 +61,7 @@ public class BulkEditGroup extends SubCommand<Datastore> {
|
||||
return CommandResult.FAILURE;
|
||||
}
|
||||
|
||||
Set<UUID> uuids = datastore.getUniqueUsers();
|
||||
Set<UUID> uuids = datastore.getUniqueUsers().getOrDefault(null);
|
||||
|
||||
for (UUID u : uuids) {
|
||||
plugin.getDatastore().loadUser(u, "null");
|
||||
|
@ -61,7 +61,7 @@ public class BulkEditPermission extends SubCommand<Datastore> {
|
||||
return CommandResult.FAILURE;
|
||||
}
|
||||
|
||||
Set<UUID> uuids = datastore.getUniqueUsers();
|
||||
Set<UUID> uuids = datastore.getUniqueUsers().getOrDefault(null);
|
||||
|
||||
for (UUID u : uuids) {
|
||||
plugin.getDatastore().loadUser(u, "null");
|
||||
|
@ -0,0 +1,195 @@
|
||||
/*
|
||||
* Copyright (c) 2016 Lucko (Luck) <luck@lucko.me>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package me.lucko.luckperms.common.storage;
|
||||
|
||||
import lombok.AccessLevel;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import me.lucko.luckperms.api.LogEntry;
|
||||
import me.lucko.luckperms.common.data.Log;
|
||||
import me.lucko.luckperms.common.groups.Group;
|
||||
import me.lucko.luckperms.common.storage.backing.AbstractBacking;
|
||||
import me.lucko.luckperms.common.tracks.Track;
|
||||
import me.lucko.luckperms.common.users.User;
|
||||
import me.lucko.luckperms.common.utils.LPFuture;
|
||||
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.Future;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
/**
|
||||
* Converts a {@link AbstractBacking} to use {@link Future}s
|
||||
*/
|
||||
@RequiredArgsConstructor(access = AccessLevel.PRIVATE)
|
||||
public class AbstractDatastore implements Datastore {
|
||||
public static Datastore wrap(AbstractBacking backing) {
|
||||
return TolerantDatastore.wrap(new AbstractDatastore(backing));
|
||||
}
|
||||
|
||||
private final AbstractBacking backing;
|
||||
|
||||
private <T> LPFuture<T> makeFuture(Supplier<T> supplier) {
|
||||
AbstractFuture<T> future = new AbstractFuture<>();
|
||||
backing.doAsync(() -> {
|
||||
T result = supplier.get();
|
||||
future.complete(result);
|
||||
});
|
||||
return future;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return backing.getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAcceptingLogins() {
|
||||
return backing.isAcceptingLogins();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setAcceptingLogins(boolean acceptingLogins) {
|
||||
backing.setAcceptingLogins(acceptingLogins);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doAsync(Runnable r) {
|
||||
backing.doAsync(r);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doSync(Runnable r) {
|
||||
backing.doSync(r);
|
||||
}
|
||||
|
||||
@Override
|
||||
public LPFuture<Void> init() {
|
||||
return makeFuture(() -> {
|
||||
backing.init();
|
||||
return null;
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public LPFuture<Void> shutdown() {
|
||||
return makeFuture(() -> {
|
||||
backing.shutdown();
|
||||
return null;
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public LPFuture<Boolean> logAction(LogEntry entry) {
|
||||
return makeFuture(() -> backing.logAction(entry));
|
||||
}
|
||||
|
||||
@Override
|
||||
public LPFuture<Log> getLog() {
|
||||
return makeFuture(backing::getLog);
|
||||
}
|
||||
|
||||
@Override
|
||||
public LPFuture<Boolean> loadUser(UUID uuid, String username) {
|
||||
return makeFuture(() -> backing.loadUser(uuid, username));
|
||||
}
|
||||
|
||||
@Override
|
||||
public LPFuture<Boolean> saveUser(User user) {
|
||||
return makeFuture(() -> backing.saveUser(user));
|
||||
}
|
||||
|
||||
@Override
|
||||
public LPFuture<Boolean> cleanupUsers() {
|
||||
return makeFuture(backing::cleanupUsers);
|
||||
}
|
||||
|
||||
@Override
|
||||
public LPFuture<Set<UUID>> getUniqueUsers() {
|
||||
return makeFuture(backing::getUniqueUsers);
|
||||
}
|
||||
|
||||
@Override
|
||||
public LPFuture<Boolean> createAndLoadGroup(String name) {
|
||||
return makeFuture(() -> backing.createAndLoadGroup(name));
|
||||
}
|
||||
|
||||
@Override
|
||||
public LPFuture<Boolean> loadGroup(String name) {
|
||||
return makeFuture(() -> backing.loadGroup(name));
|
||||
}
|
||||
|
||||
@Override
|
||||
public LPFuture<Boolean> loadAllGroups() {
|
||||
return makeFuture(backing::loadAllGroups);
|
||||
}
|
||||
|
||||
@Override
|
||||
public LPFuture<Boolean> saveGroup(Group group) {
|
||||
return makeFuture(() -> backing.saveGroup(group));
|
||||
}
|
||||
|
||||
@Override
|
||||
public LPFuture<Boolean> deleteGroup(Group group) {
|
||||
return makeFuture(() -> backing.deleteGroup(group));
|
||||
}
|
||||
|
||||
@Override
|
||||
public LPFuture<Boolean> createAndLoadTrack(String name) {
|
||||
return makeFuture(() -> backing.createAndLoadTrack(name));
|
||||
}
|
||||
|
||||
@Override
|
||||
public LPFuture<Boolean> loadTrack(String name) {
|
||||
return makeFuture(() -> backing.loadTrack(name));
|
||||
}
|
||||
|
||||
@Override
|
||||
public LPFuture<Boolean> loadAllTracks() {
|
||||
return makeFuture(backing::loadAllTracks);
|
||||
}
|
||||
|
||||
@Override
|
||||
public LPFuture<Boolean> saveTrack(Track track) {
|
||||
return makeFuture(() -> backing.saveTrack(track));
|
||||
}
|
||||
|
||||
@Override
|
||||
public LPFuture<Boolean> deleteTrack(Track track) {
|
||||
return makeFuture(() -> backing.deleteTrack(track));
|
||||
}
|
||||
|
||||
@Override
|
||||
public LPFuture<Boolean> saveUUIDData(String username, UUID uuid) {
|
||||
return makeFuture(() -> backing.saveUUIDData(username, uuid));
|
||||
}
|
||||
|
||||
@Override
|
||||
public LPFuture<UUID> getUUID(String username) {
|
||||
return makeFuture(() -> backing.getUUID(username));
|
||||
}
|
||||
|
||||
@Override
|
||||
public LPFuture<String> getName(UUID uuid) {
|
||||
return makeFuture(() -> backing.getName(uuid));
|
||||
}
|
||||
}
|
@ -0,0 +1,70 @@
|
||||
/*
|
||||
* Copyright (c) 2016 Lucko (Luck) <luck@lucko.me>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package me.lucko.luckperms.common.storage;
|
||||
|
||||
import me.lucko.luckperms.common.utils.LPFuture;
|
||||
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
|
||||
public class AbstractFuture<R> implements LPFuture<R> {
|
||||
private final CountDownLatch latch = new CountDownLatch(1);
|
||||
private R value;
|
||||
|
||||
public void complete(R r) {
|
||||
value = r;
|
||||
latch.countDown();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean cancel(boolean mayInterruptIfRunning) {
|
||||
// Not supported
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCancelled() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDone() {
|
||||
return latch.getCount() == 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public R get() throws InterruptedException {
|
||||
latch.await();
|
||||
return value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public R get(long timeout, TimeUnit unit) throws InterruptedException, TimeoutException {
|
||||
if (latch.await(timeout, unit)) {
|
||||
return value;
|
||||
} else {
|
||||
throw new TimeoutException();
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,237 @@
|
||||
/*
|
||||
* Copyright (c) 2016 Lucko (Luck) <luck@lucko.me>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package me.lucko.luckperms.common.storage;
|
||||
|
||||
import lombok.AccessLevel;
|
||||
import lombok.Getter;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import me.lucko.luckperms.api.LogEntry;
|
||||
import me.lucko.luckperms.common.data.Log;
|
||||
import me.lucko.luckperms.common.groups.Group;
|
||||
import me.lucko.luckperms.common.tracks.Track;
|
||||
import me.lucko.luckperms.common.users.User;
|
||||
import me.lucko.luckperms.common.users.UserIdentifier;
|
||||
import me.lucko.luckperms.common.utils.Buffer;
|
||||
import me.lucko.luckperms.common.utils.LPFuture;
|
||||
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
|
||||
@RequiredArgsConstructor(access = AccessLevel.PRIVATE)
|
||||
public class BufferedOutputDatastore implements Datastore, Runnable {
|
||||
public static BufferedOutputDatastore wrap(Datastore datastore, long flushTime) {
|
||||
return new BufferedOutputDatastore(datastore, flushTime);
|
||||
}
|
||||
|
||||
@Getter
|
||||
private final Datastore backing;
|
||||
|
||||
private final long flushTime;
|
||||
|
||||
private final Buffer<LogEntry, Boolean> logOutputBuffer = new Buffer<LogEntry, Boolean>() {
|
||||
@Override
|
||||
public Boolean dequeue(LogEntry logEntry) {
|
||||
return backing.logAction(logEntry).getOrDefault(false);
|
||||
}
|
||||
};
|
||||
|
||||
private final Buffer<User, Boolean> userOutputBuffer = new Buffer<User, Boolean>() {
|
||||
@Override
|
||||
public Boolean dequeue(User user) {
|
||||
return saveUser(user).getOrDefault(false);
|
||||
}
|
||||
};
|
||||
|
||||
private final Buffer<Group, Boolean> groupOutputBuffer = new Buffer<Group, Boolean>() {
|
||||
@Override
|
||||
public Boolean dequeue(Group group) {
|
||||
return saveGroup(group).getOrDefault(false);
|
||||
}
|
||||
};
|
||||
|
||||
private final Buffer<Track, Boolean> trackOutputBuffer = new Buffer<Track, Boolean>() {
|
||||
@Override
|
||||
public Boolean dequeue(Track track) {
|
||||
return saveTrack(track).getOrDefault(false);
|
||||
}
|
||||
};
|
||||
|
||||
private final Buffer<UserIdentifier, Boolean> uuidDataOutputBuffer = new Buffer<UserIdentifier, Boolean>() {
|
||||
@Override
|
||||
protected Boolean dequeue(UserIdentifier userIdentifier) {
|
||||
return saveUUIDData(userIdentifier.getUsername(), userIdentifier.getUuid()).getOrDefault(false);
|
||||
}
|
||||
};
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
flush(flushTime);
|
||||
}
|
||||
|
||||
public void forceFlush() {
|
||||
flush(-1);
|
||||
}
|
||||
|
||||
public void flush(long flushTime) {
|
||||
logOutputBuffer.flush(flushTime);
|
||||
userOutputBuffer.flush(flushTime);
|
||||
groupOutputBuffer.flush(flushTime);
|
||||
trackOutputBuffer.flush(flushTime);
|
||||
userOutputBuffer.flush(flushTime);
|
||||
}
|
||||
|
||||
public Datastore force() {
|
||||
return backing;
|
||||
}
|
||||
|
||||
@Override
|
||||
public LPFuture<Void> init() {
|
||||
return backing.init();
|
||||
}
|
||||
|
||||
@Override
|
||||
public LPFuture<Void> shutdown() {
|
||||
forceFlush();
|
||||
return backing.shutdown();
|
||||
}
|
||||
|
||||
@Override
|
||||
public LPFuture<Boolean> logAction(LogEntry entry) {
|
||||
return logOutputBuffer.enqueue(entry);
|
||||
}
|
||||
|
||||
@Override
|
||||
public LPFuture<Log> getLog() {
|
||||
return backing.getLog();
|
||||
}
|
||||
|
||||
@Override
|
||||
public LPFuture<Boolean> loadUser(UUID uuid, String username) {
|
||||
return backing.loadUser(uuid, username);
|
||||
}
|
||||
|
||||
@Override
|
||||
public LPFuture<Boolean> saveUser(User user) {
|
||||
return userOutputBuffer.enqueue(user);
|
||||
}
|
||||
|
||||
@Override
|
||||
public LPFuture<Boolean> cleanupUsers() {
|
||||
return backing.cleanupUsers();
|
||||
}
|
||||
|
||||
@Override
|
||||
public LPFuture<Set<UUID>> getUniqueUsers() {
|
||||
return backing.getUniqueUsers();
|
||||
}
|
||||
|
||||
@Override
|
||||
public LPFuture<Boolean> createAndLoadGroup(String name) {
|
||||
return backing.createAndLoadGroup(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public LPFuture<Boolean> loadGroup(String name) {
|
||||
return backing.loadGroup(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public LPFuture<Boolean> loadAllGroups() {
|
||||
return backing.loadAllGroups();
|
||||
}
|
||||
|
||||
@Override
|
||||
public LPFuture<Boolean> saveGroup(Group group) {
|
||||
return groupOutputBuffer.enqueue(group);
|
||||
}
|
||||
|
||||
@Override
|
||||
public LPFuture<Boolean> deleteGroup(Group group) {
|
||||
return backing.deleteGroup(group);
|
||||
}
|
||||
|
||||
@Override
|
||||
public LPFuture<Boolean> createAndLoadTrack(String name) {
|
||||
return backing.createAndLoadTrack(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public LPFuture<Boolean> loadTrack(String name) {
|
||||
return backing.loadTrack(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public LPFuture<Boolean> loadAllTracks() {
|
||||
return backing.loadAllTracks();
|
||||
}
|
||||
|
||||
@Override
|
||||
public LPFuture<Boolean> saveTrack(Track track) {
|
||||
return trackOutputBuffer.enqueue(track);
|
||||
}
|
||||
|
||||
@Override
|
||||
public LPFuture<Boolean> deleteTrack(Track track) {
|
||||
return backing.deleteTrack(track);
|
||||
}
|
||||
|
||||
@Override
|
||||
public LPFuture<Boolean> saveUUIDData(String username, UUID uuid) {
|
||||
return uuidDataOutputBuffer.enqueue(UserIdentifier.of(uuid, username));
|
||||
}
|
||||
|
||||
@Override
|
||||
public LPFuture<UUID> getUUID(String username) {
|
||||
return backing.getUUID(username);
|
||||
}
|
||||
|
||||
@Override
|
||||
public LPFuture<String> getName(UUID uuid) {
|
||||
return backing.getName(uuid);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return backing.getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAcceptingLogins() {
|
||||
return backing.isAcceptingLogins();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setAcceptingLogins(boolean acceptingLogins) {
|
||||
backing.setAcceptingLogins(acceptingLogins);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doAsync(Runnable r) {
|
||||
backing.doAsync(r);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doSync(Runnable r) {
|
||||
backing.doSync(r);
|
||||
}
|
||||
}
|
@ -22,208 +22,191 @@
|
||||
|
||||
package me.lucko.luckperms.common.storage;
|
||||
|
||||
import lombok.AccessLevel;
|
||||
import lombok.Getter;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.Setter;
|
||||
import me.lucko.luckperms.api.LogEntry;
|
||||
import me.lucko.luckperms.api.data.Callback;
|
||||
import me.lucko.luckperms.common.LuckPermsPlugin;
|
||||
import me.lucko.luckperms.common.data.Log;
|
||||
import me.lucko.luckperms.common.groups.Group;
|
||||
import me.lucko.luckperms.common.tracks.Track;
|
||||
import me.lucko.luckperms.common.users.User;
|
||||
import me.lucko.luckperms.common.utils.LPFuture;
|
||||
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
|
||||
@RequiredArgsConstructor(access = AccessLevel.PROTECTED)
|
||||
public abstract class Datastore {
|
||||
protected final LuckPermsPlugin plugin;
|
||||
|
||||
@Getter
|
||||
public final String name;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
private boolean acceptingLogins = false;
|
||||
public interface Datastore {
|
||||
|
||||
String getName();
|
||||
|
||||
boolean isAcceptingLogins();
|
||||
void setAcceptingLogins(boolean acceptingLogins);
|
||||
|
||||
/**
|
||||
* Execute a runnable asynchronously
|
||||
* @param r the task to run
|
||||
*/
|
||||
private void doAsync(Runnable r) {
|
||||
plugin.doAsync(r);
|
||||
}
|
||||
void doAsync(Runnable r);
|
||||
|
||||
/**
|
||||
* Execute a runnable synchronously
|
||||
* @param r the task to run
|
||||
*/
|
||||
private void doSync(Runnable r) {
|
||||
plugin.doSync(r);
|
||||
void doSync(Runnable r);
|
||||
|
||||
default Datastore force() {
|
||||
return this;
|
||||
}
|
||||
|
||||
/*
|
||||
These methods are called immediately and in the same thread as they are called in.
|
||||
*/
|
||||
public abstract void init();
|
||||
public abstract void shutdown();
|
||||
public abstract boolean logAction(LogEntry entry);
|
||||
public abstract Log getLog();
|
||||
public abstract boolean loadUser(UUID uuid, String username);
|
||||
public abstract boolean saveUser(User user);
|
||||
public abstract boolean cleanupUsers();
|
||||
public abstract Set<UUID> getUniqueUsers();
|
||||
public abstract boolean createAndLoadGroup(String name);
|
||||
public abstract boolean loadGroup(String name);
|
||||
public abstract boolean loadAllGroups();
|
||||
public abstract boolean saveGroup(Group group);
|
||||
public abstract boolean deleteGroup(Group group);
|
||||
public abstract boolean createAndLoadTrack(String name);
|
||||
public abstract boolean loadTrack(String name);
|
||||
public abstract boolean loadAllTracks();
|
||||
public abstract boolean saveTrack(Track track);
|
||||
public abstract boolean deleteTrack(Track track);
|
||||
public abstract boolean saveUUIDData(String username, UUID uuid);
|
||||
public abstract UUID getUUID(String username);
|
||||
public abstract String getName(UUID uuid);
|
||||
LPFuture<Void> init();
|
||||
LPFuture<Void> shutdown();
|
||||
LPFuture<Boolean> logAction(LogEntry entry);
|
||||
LPFuture<Log> getLog();
|
||||
LPFuture<Boolean> loadUser(UUID uuid, String username);
|
||||
LPFuture<Boolean> saveUser(User user);
|
||||
LPFuture<Boolean> cleanupUsers();
|
||||
LPFuture<Set<UUID>> getUniqueUsers();
|
||||
LPFuture<Boolean> createAndLoadGroup(String name);
|
||||
LPFuture<Boolean> loadGroup(String name);
|
||||
LPFuture<Boolean> loadAllGroups();
|
||||
LPFuture<Boolean> saveGroup(Group group);
|
||||
LPFuture<Boolean> deleteGroup(Group group);
|
||||
LPFuture<Boolean> createAndLoadTrack(String name);
|
||||
LPFuture<Boolean> loadTrack(String name);
|
||||
LPFuture<Boolean> loadAllTracks();
|
||||
LPFuture<Boolean> saveTrack(Track track);
|
||||
LPFuture<Boolean> deleteTrack(Track track);
|
||||
LPFuture<Boolean> saveUUIDData(String username, UUID uuid);
|
||||
LPFuture<UUID> getUUID(String username);
|
||||
LPFuture<String> getName(UUID uuid);
|
||||
|
||||
|
||||
|
||||
/*
|
||||
These methods will schedule the operation to run async. The callback will be ran when the task is complete.
|
||||
Callbacks are ran on the main server thread (except on BungeeCord)
|
||||
*/
|
||||
public void logAction(LogEntry entry, Callback<Boolean> callback) {
|
||||
default void logAction(LogEntry entry, Callback<Boolean> callback) {
|
||||
doAsync(() -> {
|
||||
boolean result = logAction(entry);
|
||||
boolean result = logAction(entry).getOrDefault(false);
|
||||
doSync(() -> callback.onComplete(result));
|
||||
});
|
||||
}
|
||||
|
||||
public void getLog(Callback<Log> callback) {
|
||||
default void getLog(Callback<Log> callback) {
|
||||
doAsync(() -> {
|
||||
Log result = getLog();
|
||||
Log result = getLog().getOrDefault(null);
|
||||
doSync(() -> callback.onComplete(result));
|
||||
});
|
||||
}
|
||||
|
||||
public void loadUser(UUID uuid, String username, Callback<Boolean> callback) {
|
||||
default void loadUser(UUID uuid, String username, Callback<Boolean> callback) {
|
||||
doAsync(() -> {
|
||||
boolean result = loadUser(uuid, username);
|
||||
boolean result = loadUser(uuid, username).getOrDefault(false);
|
||||
doSync(() -> callback.onComplete(result));
|
||||
});
|
||||
}
|
||||
|
||||
public void saveUser(User user, Callback<Boolean> callback) {
|
||||
default void saveUser(User user, Callback<Boolean> callback) {
|
||||
doAsync(() -> {
|
||||
boolean result = saveUser(user);
|
||||
boolean result = saveUser(user).getOrDefault(false);
|
||||
doSync(() -> callback.onComplete(result));
|
||||
});
|
||||
}
|
||||
|
||||
public void cleanupUsers(Callback<Boolean> callback) {
|
||||
default void cleanupUsers(Callback<Boolean> callback) {
|
||||
doAsync(() -> {
|
||||
boolean result = cleanupUsers();
|
||||
boolean result = cleanupUsers().getOrDefault(false);
|
||||
doSync(() -> callback.onComplete(result));
|
||||
});
|
||||
}
|
||||
|
||||
public void getUniqueUsers(Callback<Set<UUID>> callback) {
|
||||
default void getUniqueUsers(Callback<Set<UUID>> callback) {
|
||||
doAsync(() -> {
|
||||
Set<UUID> result = getUniqueUsers();
|
||||
Set<UUID> result = getUniqueUsers().getOrDefault(null);
|
||||
doSync(() -> callback.onComplete(result));
|
||||
});
|
||||
}
|
||||
|
||||
public void createAndLoadGroup(String name, Callback<Boolean> callback) {
|
||||
default void createAndLoadGroup(String name, Callback<Boolean> callback) {
|
||||
doAsync(() -> {
|
||||
boolean result = createAndLoadGroup(name);
|
||||
boolean result = createAndLoadGroup(name).getOrDefault(false);
|
||||
doSync(() -> callback.onComplete(result));
|
||||
});
|
||||
}
|
||||
|
||||
public void loadGroup(String name, Callback<Boolean> callback) {
|
||||
default void loadGroup(String name, Callback<Boolean> callback) {
|
||||
doAsync(() -> {
|
||||
boolean result = loadGroup(name);
|
||||
boolean result = loadGroup(name).getOrDefault(false);
|
||||
doSync(() -> callback.onComplete(result));
|
||||
});
|
||||
}
|
||||
|
||||
public void loadAllGroups(Callback<Boolean> callback) {
|
||||
default void loadAllGroups(Callback<Boolean> callback) {
|
||||
doAsync(() -> {
|
||||
boolean result = loadAllGroups();
|
||||
boolean result = loadAllGroups().getOrDefault(false);
|
||||
doSync(() -> callback.onComplete(result));
|
||||
});
|
||||
}
|
||||
|
||||
public void saveGroup(Group group, Callback<Boolean> callback) {
|
||||
default void saveGroup(Group group, Callback<Boolean> callback) {
|
||||
doAsync(() -> {
|
||||
boolean result = saveGroup(group);
|
||||
boolean result = saveGroup(group).getOrDefault(false);
|
||||
doSync(() -> callback.onComplete(result));
|
||||
});
|
||||
}
|
||||
|
||||
public void deleteGroup(Group group, Callback<Boolean> callback) {
|
||||
default void deleteGroup(Group group, Callback<Boolean> callback) {
|
||||
doAsync(() -> {
|
||||
boolean result = deleteGroup(group);
|
||||
boolean result = deleteGroup(group).getOrDefault(false);
|
||||
doSync(() -> callback.onComplete(result));
|
||||
});
|
||||
}
|
||||
|
||||
public void createAndLoadTrack(String name, Callback<Boolean> callback) {
|
||||
default void createAndLoadTrack(String name, Callback<Boolean> callback) {
|
||||
doAsync(() -> {
|
||||
boolean result = createAndLoadTrack(name);
|
||||
boolean result = createAndLoadTrack(name).getOrDefault(false);
|
||||
doSync(() -> callback.onComplete(result));
|
||||
});
|
||||
}
|
||||
|
||||
public void loadTrack(String name, Callback<Boolean> callback) {
|
||||
default void loadTrack(String name, Callback<Boolean> callback) {
|
||||
doAsync(() -> {
|
||||
boolean result = loadTrack(name);
|
||||
boolean result = loadTrack(name).getOrDefault(false);
|
||||
doSync(() -> callback.onComplete(result));
|
||||
});
|
||||
}
|
||||
|
||||
public void loadAllTracks(Callback<Boolean> callback) {
|
||||
default void loadAllTracks(Callback<Boolean> callback) {
|
||||
doAsync(() -> {
|
||||
boolean result = loadAllTracks();
|
||||
boolean result = loadAllTracks().getOrDefault(false);
|
||||
doSync(() -> callback.onComplete(result));
|
||||
});
|
||||
}
|
||||
|
||||
public void saveTrack(Track track, Callback<Boolean> callback) {
|
||||
default void saveTrack(Track track, Callback<Boolean> callback) {
|
||||
doAsync(() -> {
|
||||
boolean result = saveTrack(track);
|
||||
boolean result = saveTrack(track).getOrDefault(false);
|
||||
doSync(() -> callback.onComplete(result));
|
||||
});
|
||||
}
|
||||
|
||||
public void deleteTrack(Track track, Callback<Boolean> callback) {
|
||||
default void deleteTrack(Track track, Callback<Boolean> callback) {
|
||||
doAsync(() -> {
|
||||
boolean result = deleteTrack(track);
|
||||
boolean result = deleteTrack(track).getOrDefault(false);
|
||||
doSync(() -> callback.onComplete(result));
|
||||
});
|
||||
}
|
||||
|
||||
public void saveUUIDData(String username, UUID uuid, Callback<Boolean> callback) {
|
||||
default void saveUUIDData(String username, UUID uuid, Callback<Boolean> callback) {
|
||||
doAsync(() -> {
|
||||
boolean result = saveUUIDData(username, uuid);
|
||||
boolean result = saveUUIDData(username, uuid).getOrDefault(false);
|
||||
doSync(() -> callback.onComplete(result));
|
||||
});
|
||||
}
|
||||
|
||||
public void getUUID(String username, Callback<UUID> callback) {
|
||||
default void getUUID(String username, Callback<UUID> callback) {
|
||||
doAsync(() -> {
|
||||
UUID result = getUUID(username);
|
||||
UUID result = getUUID(username).getOrDefault(null);
|
||||
doSync(() -> callback.onComplete(result));
|
||||
});
|
||||
}
|
||||
|
||||
public void getName(UUID uuid, Callback<String> callback) {
|
||||
default void getName(UUID uuid, Callback<String> callback) {
|
||||
doAsync(() -> {
|
||||
String result = getName(uuid);
|
||||
String result = getName(uuid).getOrDefault(null);
|
||||
doSync(() -> callback.onComplete(result));
|
||||
});
|
||||
}
|
||||
|
@ -23,136 +23,172 @@
|
||||
package me.lucko.luckperms.common.storage;
|
||||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import me.lucko.luckperms.api.LogEntry;
|
||||
import me.lucko.luckperms.common.LuckPermsPlugin;
|
||||
import me.lucko.luckperms.common.data.Log;
|
||||
import me.lucko.luckperms.common.groups.Group;
|
||||
import me.lucko.luckperms.common.tracks.Track;
|
||||
import me.lucko.luckperms.common.users.User;
|
||||
import me.lucko.luckperms.common.utils.LPFuture;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
|
||||
public class SplitDatastore extends Datastore {
|
||||
public class SplitBacking implements Datastore {
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
private boolean acceptingLogins = false;
|
||||
|
||||
private final LuckPermsPlugin plugin;
|
||||
private final Map<String, Datastore> backing;
|
||||
private final Map<String, String> types;
|
||||
|
||||
protected SplitDatastore(LuckPermsPlugin plugin, Map<String, Datastore> backing, Map<String, String> types) {
|
||||
super(plugin, "Split Storage");
|
||||
protected SplitBacking(LuckPermsPlugin plugin, Map<String, Datastore> backing, Map<String, String> types) {
|
||||
this.plugin = plugin;
|
||||
this.backing = ImmutableMap.copyOf(backing);
|
||||
this.types = ImmutableMap.copyOf(types);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init() {
|
||||
backing.values().forEach(Datastore::init);
|
||||
for (Datastore ds : backing.values()) {
|
||||
if (!ds.isAcceptingLogins()) {
|
||||
return;
|
||||
public String getName() {
|
||||
return "Split Storage";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doAsync(Runnable r) {
|
||||
plugin.doAsync(r);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doSync(Runnable r) {
|
||||
plugin.doSync(r);
|
||||
}
|
||||
|
||||
@Override
|
||||
public LPFuture<Void> init() {
|
||||
AbstractFuture<Void> future = new AbstractFuture<>();
|
||||
doAsync(() -> {
|
||||
boolean success = true;
|
||||
backing.values().forEach(Datastore::init);
|
||||
for (Datastore ds : backing.values()) {
|
||||
if (!ds.isAcceptingLogins()) {
|
||||
success = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
setAcceptingLogins(true);
|
||||
setAcceptingLogins(success);
|
||||
future.complete(null);
|
||||
});
|
||||
return future;
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void shutdown() {
|
||||
backing.values().forEach(Datastore::shutdown);
|
||||
public LPFuture<Void> shutdown() {
|
||||
AbstractFuture<Void> future = new AbstractFuture<>();
|
||||
doAsync(() -> {
|
||||
backing.values().forEach(Datastore::shutdown);
|
||||
future.complete(null);
|
||||
});
|
||||
return future;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean logAction(LogEntry entry) {
|
||||
public LPFuture<Boolean> logAction(LogEntry entry) {
|
||||
return backing.get(types.get("log")).logAction(entry);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Log getLog() {
|
||||
public LPFuture<Log> getLog() {
|
||||
return backing.get(types.get("log")).getLog();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean loadUser(UUID uuid, String username) {
|
||||
public LPFuture<Boolean> loadUser(UUID uuid, String username) {
|
||||
return backing.get(types.get("user")).loadUser(uuid, username);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean saveUser(User user) {
|
||||
public LPFuture<Boolean> saveUser(User user) {
|
||||
return backing.get(types.get("user")).saveUser(user);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean cleanupUsers() {
|
||||
public LPFuture<Boolean> cleanupUsers() {
|
||||
return backing.get(types.get("user")).cleanupUsers();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<UUID> getUniqueUsers() {
|
||||
public LPFuture<Set<UUID>> getUniqueUsers() {
|
||||
return backing.get(types.get("user")).getUniqueUsers();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean createAndLoadGroup(String name) {
|
||||
public LPFuture<Boolean> createAndLoadGroup(String name) {
|
||||
return backing.get(types.get("group")).createAndLoadGroup(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean loadGroup(String name) {
|
||||
public LPFuture<Boolean> loadGroup(String name) {
|
||||
return backing.get(types.get("group")).loadGroup(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean loadAllGroups() {
|
||||
public LPFuture<Boolean> loadAllGroups() {
|
||||
return backing.get(types.get("group")).loadAllGroups();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean saveGroup(Group group) {
|
||||
public LPFuture<Boolean> saveGroup(Group group) {
|
||||
return backing.get(types.get("group")).saveGroup(group);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean deleteGroup(Group group) {
|
||||
public LPFuture<Boolean> deleteGroup(Group group) {
|
||||
return backing.get(types.get("group")).deleteGroup(group);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean createAndLoadTrack(String name) {
|
||||
public LPFuture<Boolean> createAndLoadTrack(String name) {
|
||||
return backing.get(types.get("track")).createAndLoadTrack(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean loadTrack(String name) {
|
||||
public LPFuture<Boolean> loadTrack(String name) {
|
||||
return backing.get(types.get("track")).loadTrack(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean loadAllTracks() {
|
||||
public LPFuture<Boolean> loadAllTracks() {
|
||||
return backing.get(types.get("track")).loadAllTracks();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean saveTrack(Track track) {
|
||||
public LPFuture<Boolean> saveTrack(Track track) {
|
||||
return backing.get(types.get("track")).saveTrack(track);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean deleteTrack(Track track) {
|
||||
public LPFuture<Boolean> deleteTrack(Track track) {
|
||||
return backing.get(types.get("track")).deleteTrack(track);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean saveUUIDData(String username, UUID uuid) {
|
||||
public LPFuture<Boolean> saveUUIDData(String username, UUID uuid) {
|
||||
return backing.get(types.get("uuid")).saveUUIDData(username, uuid);
|
||||
}
|
||||
|
||||
@Override
|
||||
public UUID getUUID(String username) {
|
||||
public LPFuture<UUID> getUUID(String username) {
|
||||
return backing.get(types.get("uuid")).getUUID(username);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName(UUID uuid) {
|
||||
public LPFuture<String> getName(UUID uuid) {
|
||||
return backing.get(types.get("uuid")).getName(uuid);
|
||||
}
|
||||
}
|
@ -25,7 +25,7 @@ package me.lucko.luckperms.common.storage;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import lombok.experimental.UtilityClass;
|
||||
import me.lucko.luckperms.common.LuckPermsPlugin;
|
||||
import me.lucko.luckperms.common.storage.methods.*;
|
||||
import me.lucko.luckperms.common.storage.backing.*;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.HashMap;
|
||||
@ -63,7 +63,7 @@ public class StorageFactory {
|
||||
backing.put(type, fromString(type, plugin));
|
||||
}
|
||||
|
||||
datastore = new SplitDatastore(plugin, backing, types);
|
||||
datastore = new SplitBacking(plugin, backing, types);
|
||||
|
||||
} else {
|
||||
String storageMethod = plugin.getConfiguration().getStorageMethod().toLowerCase();
|
||||
@ -77,24 +77,26 @@ public class StorageFactory {
|
||||
}
|
||||
|
||||
plugin.getLog().info("Initialising datastore...");
|
||||
datastore.init();
|
||||
datastore.init().getOrDefault(null);
|
||||
return datastore;
|
||||
}
|
||||
|
||||
private static Datastore fromString(String storageMethod, LuckPermsPlugin plugin) {
|
||||
switch (storageMethod) {
|
||||
case "mysql":
|
||||
return new MySQLDatastore(plugin, plugin.getConfiguration().getDatabaseValues());
|
||||
BufferedOutputDatastore bod = BufferedOutputDatastore.wrap(AbstractDatastore.wrap(new MySQLBacking(plugin, plugin.getConfiguration().getDatabaseValues())), 5000L);
|
||||
plugin.doAsyncRepeating(bod, 20L);
|
||||
return bod;
|
||||
case "sqlite":
|
||||
return new SQLiteDatastore(plugin, new File(plugin.getDataFolder(), "luckperms.sqlite"));
|
||||
return AbstractDatastore.wrap(new SQLiteBacking(plugin, new File(plugin.getDataFolder(), "luckperms.sqlite")));
|
||||
case "h2":
|
||||
return new H2Datastore(plugin, new File(plugin.getDataFolder(), "luckperms.db"));
|
||||
return AbstractDatastore.wrap(new H2Backing(plugin, new File(plugin.getDataFolder(), "luckperms.db")));
|
||||
case "mongodb":
|
||||
return new MongoDBDatastore(plugin, plugin.getConfiguration().getDatabaseValues());
|
||||
return AbstractDatastore.wrap(new MongoDBBacking(plugin, plugin.getConfiguration().getDatabaseValues()));
|
||||
case "yaml":
|
||||
return new YAMLDatastore(plugin, plugin.getDataFolder());
|
||||
return AbstractDatastore.wrap(new YAMLBacking(plugin, plugin.getDataFolder()));
|
||||
default:
|
||||
return new JSONDatastore(plugin, plugin.getDataFolder());
|
||||
return AbstractDatastore.wrap(new JSONBacking(plugin, plugin.getDataFolder()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,282 @@
|
||||
/*
|
||||
* Copyright (c) 2016 Lucko (Luck) <luck@lucko.me>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package me.lucko.luckperms.common.storage;
|
||||
|
||||
import lombok.AccessLevel;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import me.lucko.luckperms.api.LogEntry;
|
||||
import me.lucko.luckperms.common.data.Log;
|
||||
import me.lucko.luckperms.common.groups.Group;
|
||||
import me.lucko.luckperms.common.tracks.Track;
|
||||
import me.lucko.luckperms.common.users.User;
|
||||
import me.lucko.luckperms.common.utils.LPFuture;
|
||||
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.Phaser;
|
||||
|
||||
/**
|
||||
* A Datastore wrapping that ensures all tasks are completed before {@link Datastore#shutdown()} is called.
|
||||
*/
|
||||
@RequiredArgsConstructor(access = AccessLevel.PRIVATE)
|
||||
public class TolerantDatastore implements Datastore {
|
||||
public static TolerantDatastore wrap(Datastore datastore) {
|
||||
return new TolerantDatastore(datastore);
|
||||
}
|
||||
|
||||
private final Datastore backing;
|
||||
private final Phaser phaser = new Phaser();
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return backing.getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAcceptingLogins() {
|
||||
return backing.isAcceptingLogins();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setAcceptingLogins(boolean acceptingLogins) {
|
||||
backing.setAcceptingLogins(acceptingLogins);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doAsync(Runnable r) {
|
||||
backing.doAsync(r);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doSync(Runnable r) {
|
||||
backing.doSync(r);
|
||||
}
|
||||
|
||||
@Override
|
||||
public LPFuture<Void> init() {
|
||||
phaser.register();
|
||||
try {
|
||||
return backing.init();
|
||||
} finally {
|
||||
phaser.arriveAndDeregister();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public LPFuture<Void> shutdown() {
|
||||
phaser.register(); // Register self
|
||||
phaser.arriveAndAwaitAdvance(); // Wait for other threads to finish.
|
||||
|
||||
return backing.shutdown();
|
||||
}
|
||||
|
||||
@Override
|
||||
public LPFuture<Boolean> logAction(LogEntry entry) {
|
||||
phaser.register();
|
||||
try {
|
||||
return backing.logAction(entry);
|
||||
} finally {
|
||||
phaser.arriveAndDeregister();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public LPFuture<Log> getLog() {
|
||||
phaser.register();
|
||||
try {
|
||||
return backing.getLog();
|
||||
} finally {
|
||||
phaser.arriveAndDeregister();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public LPFuture<Boolean> loadUser(UUID uuid, String username) {
|
||||
phaser.register();
|
||||
try {
|
||||
return backing.loadUser(uuid, username);
|
||||
} finally {
|
||||
phaser.arriveAndDeregister();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public LPFuture<Boolean> saveUser(User user) {
|
||||
phaser.register();
|
||||
try {
|
||||
return backing.saveUser(user);
|
||||
} finally {
|
||||
phaser.arriveAndDeregister();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public LPFuture<Boolean> cleanupUsers() {
|
||||
phaser.register();
|
||||
try {
|
||||
return backing.cleanupUsers();
|
||||
} finally {
|
||||
phaser.arriveAndDeregister();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public LPFuture<Set<UUID>> getUniqueUsers() {
|
||||
phaser.register();
|
||||
try {
|
||||
return backing.getUniqueUsers();
|
||||
} finally {
|
||||
phaser.arriveAndDeregister();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public LPFuture<Boolean> createAndLoadGroup(String name) {
|
||||
phaser.register();
|
||||
try {
|
||||
return backing.createAndLoadGroup(name);
|
||||
} finally {
|
||||
phaser.arriveAndDeregister();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public LPFuture<Boolean> loadGroup(String name) {
|
||||
phaser.register();
|
||||
try {
|
||||
return backing.loadGroup(name);
|
||||
} finally {
|
||||
phaser.arriveAndDeregister();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public LPFuture<Boolean> loadAllGroups() {
|
||||
phaser.register();
|
||||
try {
|
||||
return backing.loadAllGroups();
|
||||
} finally {
|
||||
phaser.arriveAndDeregister();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public LPFuture<Boolean> saveGroup(Group group) {
|
||||
phaser.register();
|
||||
try {
|
||||
return backing.saveGroup(group);
|
||||
} finally {
|
||||
phaser.arriveAndDeregister();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public LPFuture<Boolean> deleteGroup(Group group) {
|
||||
phaser.register();
|
||||
try {
|
||||
return backing.deleteGroup(group);
|
||||
} finally {
|
||||
phaser.arriveAndDeregister();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public LPFuture<Boolean> createAndLoadTrack(String name) {
|
||||
phaser.register();
|
||||
try {
|
||||
return backing.createAndLoadTrack(name);
|
||||
} finally {
|
||||
phaser.arriveAndDeregister();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public LPFuture<Boolean> loadTrack(String name) {
|
||||
phaser.register();
|
||||
try {
|
||||
return backing.loadTrack(name);
|
||||
} finally {
|
||||
phaser.arriveAndDeregister();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public LPFuture<Boolean> loadAllTracks() {
|
||||
phaser.register();
|
||||
try {
|
||||
return backing.loadAllTracks();
|
||||
} finally {
|
||||
phaser.arriveAndDeregister();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public LPFuture<Boolean> saveTrack(Track track) {
|
||||
phaser.register();
|
||||
try {
|
||||
return backing.saveTrack(track);
|
||||
} finally {
|
||||
phaser.arriveAndDeregister();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public LPFuture<Boolean> deleteTrack(Track track) {
|
||||
phaser.register();
|
||||
try {
|
||||
return backing.deleteTrack(track);
|
||||
} finally {
|
||||
phaser.arriveAndDeregister();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public LPFuture<Boolean> saveUUIDData(String username, UUID uuid) {
|
||||
phaser.register();
|
||||
try {
|
||||
return backing.saveUUIDData(username, uuid);
|
||||
} finally {
|
||||
phaser.arriveAndDeregister();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public LPFuture<UUID> getUUID(String username) {
|
||||
phaser.register();
|
||||
try {
|
||||
return backing.getUUID(username);
|
||||
} finally {
|
||||
phaser.arriveAndDeregister();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public LPFuture<String> getName(UUID uuid) {
|
||||
phaser.register();
|
||||
try {
|
||||
return backing.getName(uuid);
|
||||
} finally {
|
||||
phaser.arriveAndDeregister();
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,88 @@
|
||||
/*
|
||||
* Copyright (c) 2016 Lucko (Luck) <luck@lucko.me>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package me.lucko.luckperms.common.storage.backing;
|
||||
|
||||
import lombok.AccessLevel;
|
||||
import lombok.Getter;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.Setter;
|
||||
import me.lucko.luckperms.api.LogEntry;
|
||||
import me.lucko.luckperms.common.LuckPermsPlugin;
|
||||
import me.lucko.luckperms.common.data.Log;
|
||||
import me.lucko.luckperms.common.groups.Group;
|
||||
import me.lucko.luckperms.common.tracks.Track;
|
||||
import me.lucko.luckperms.common.users.User;
|
||||
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
|
||||
@RequiredArgsConstructor(access = AccessLevel.PROTECTED)
|
||||
public abstract class AbstractBacking {
|
||||
protected final LuckPermsPlugin plugin;
|
||||
|
||||
@Getter
|
||||
public final String name;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
private boolean acceptingLogins = false;
|
||||
|
||||
/**
|
||||
* Execute a runnable asynchronously
|
||||
* @param r the task to run
|
||||
*/
|
||||
public void doAsync(Runnable r) {
|
||||
plugin.doAsync(r);
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute a runnable synchronously
|
||||
* @param r the task to run
|
||||
*/
|
||||
public void doSync(Runnable r) {
|
||||
plugin.doSync(r);
|
||||
}
|
||||
|
||||
public abstract void init();
|
||||
public abstract void shutdown();
|
||||
public abstract boolean logAction(LogEntry entry);
|
||||
public abstract Log getLog();
|
||||
public abstract boolean loadUser(UUID uuid, String username);
|
||||
public abstract boolean saveUser(User user);
|
||||
public abstract boolean cleanupUsers();
|
||||
public abstract Set<UUID> getUniqueUsers();
|
||||
public abstract boolean createAndLoadGroup(String name);
|
||||
public abstract boolean loadGroup(String name);
|
||||
public abstract boolean loadAllGroups();
|
||||
public abstract boolean saveGroup(Group group);
|
||||
public abstract boolean deleteGroup(Group group);
|
||||
public abstract boolean createAndLoadTrack(String name);
|
||||
public abstract boolean loadTrack(String name);
|
||||
public abstract boolean loadAllTracks();
|
||||
public abstract boolean saveTrack(Track track);
|
||||
public abstract boolean deleteTrack(Track track);
|
||||
public abstract boolean saveUUIDData(String username, UUID uuid);
|
||||
public abstract UUID getUUID(String username);
|
||||
public abstract String getName(UUID uuid);
|
||||
|
||||
}
|
@ -20,14 +20,13 @@
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package me.lucko.luckperms.common.storage.methods;
|
||||
package me.lucko.luckperms.common.storage.backing;
|
||||
|
||||
import lombok.Cleanup;
|
||||
import me.lucko.luckperms.api.LogEntry;
|
||||
import me.lucko.luckperms.common.LuckPermsPlugin;
|
||||
import me.lucko.luckperms.common.constants.Constants;
|
||||
import me.lucko.luckperms.common.data.Log;
|
||||
import me.lucko.luckperms.common.storage.Datastore;
|
||||
|
||||
import java.io.*;
|
||||
import java.util.*;
|
||||
@ -35,7 +34,7 @@ import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.logging.*;
|
||||
import java.util.logging.Formatter;
|
||||
|
||||
abstract class FlatfileDatastore extends Datastore {
|
||||
abstract class FlatfileBacking extends AbstractBacking {
|
||||
private static final String LOG_FORMAT = "%s(%s): [%s] %s(%s) --> %s";
|
||||
|
||||
private final Logger actionLogger = Logger.getLogger("lp_actions");
|
||||
@ -48,7 +47,7 @@ abstract class FlatfileDatastore extends Datastore {
|
||||
File groupsDir;
|
||||
File tracksDir;
|
||||
|
||||
FlatfileDatastore(LuckPermsPlugin plugin, String name, File pluginDir) {
|
||||
FlatfileBacking(LuckPermsPlugin plugin, String name, File pluginDir) {
|
||||
super(plugin, name);
|
||||
this.pluginDir = pluginDir;
|
||||
}
|
@ -20,7 +20,7 @@
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package me.lucko.luckperms.common.storage.methods;
|
||||
package me.lucko.luckperms.common.storage.backing;
|
||||
|
||||
import lombok.Cleanup;
|
||||
import me.lucko.luckperms.common.LuckPermsPlugin;
|
||||
@ -28,7 +28,7 @@ import me.lucko.luckperms.common.LuckPermsPlugin;
|
||||
import java.io.File;
|
||||
import java.sql.*;
|
||||
|
||||
public class H2Datastore extends SQLDatastore {
|
||||
public class H2Backing extends SQLBacking {
|
||||
|
||||
private static final String CREATETABLE_UUID = "CREATE TABLE IF NOT EXISTS `lp_uuid` (`name` VARCHAR(16) NOT NULL, `uuid` VARCHAR(36) NOT NULL, PRIMARY KEY (`name`)) DEFAULT CHARSET=utf8;";
|
||||
private static final String CREATETABLE_USERS = "CREATE TABLE IF NOT EXISTS `lp_users` (`uuid` VARCHAR(36) NOT NULL, `name` VARCHAR(16) NOT NULL, `primary_group` VARCHAR(36) NOT NULL, `perms` TEXT NOT NULL, PRIMARY KEY (`uuid`)) DEFAULT CHARSET=utf8;";
|
||||
@ -40,7 +40,7 @@ public class H2Datastore extends SQLDatastore {
|
||||
private Connection connection = null;
|
||||
private final Object connectionLock = new Object();
|
||||
|
||||
public H2Datastore(LuckPermsPlugin plugin, File file) {
|
||||
public H2Backing(LuckPermsPlugin plugin, File file) {
|
||||
super(plugin, "H2");
|
||||
this.file = file;
|
||||
}
|
@ -20,7 +20,7 @@
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package me.lucko.luckperms.common.storage.methods;
|
||||
package me.lucko.luckperms.common.storage.backing;
|
||||
|
||||
import com.google.gson.stream.JsonReader;
|
||||
import com.google.gson.stream.JsonWriter;
|
||||
@ -42,8 +42,8 @@ import java.util.stream.Collectors;
|
||||
import static me.lucko.luckperms.common.core.PermissionHolder.exportToLegacy;
|
||||
|
||||
@SuppressWarnings("ResultOfMethodCallIgnored")
|
||||
public class JSONDatastore extends FlatfileDatastore {
|
||||
public JSONDatastore(LuckPermsPlugin plugin, File pluginDir) {
|
||||
public class JSONBacking extends FlatfileBacking {
|
||||
public JSONBacking(LuckPermsPlugin plugin, File pluginDir) {
|
||||
super(plugin, "Flatfile - JSON", pluginDir);
|
||||
}
|
||||
|
@ -20,7 +20,7 @@
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package me.lucko.luckperms.common.storage.methods;
|
||||
package me.lucko.luckperms.common.storage.backing;
|
||||
|
||||
import com.mongodb.MongoClient;
|
||||
import com.mongodb.MongoCredential;
|
||||
@ -34,7 +34,6 @@ import me.lucko.luckperms.common.LuckPermsPlugin;
|
||||
import me.lucko.luckperms.common.data.Log;
|
||||
import me.lucko.luckperms.common.groups.Group;
|
||||
import me.lucko.luckperms.common.groups.GroupManager;
|
||||
import me.lucko.luckperms.common.storage.Datastore;
|
||||
import me.lucko.luckperms.common.storage.DatastoreConfiguration;
|
||||
import me.lucko.luckperms.common.tracks.Track;
|
||||
import me.lucko.luckperms.common.tracks.TrackManager;
|
||||
@ -49,13 +48,13 @@ import java.util.stream.Collectors;
|
||||
import static me.lucko.luckperms.common.core.PermissionHolder.exportToLegacy;
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public class MongoDBDatastore extends Datastore {
|
||||
public class MongoDBBacking extends AbstractBacking {
|
||||
|
||||
private final DatastoreConfiguration configuration;
|
||||
private MongoClient mongoClient;
|
||||
private MongoDatabase database;
|
||||
|
||||
public MongoDBDatastore(LuckPermsPlugin plugin, DatastoreConfiguration configuration) {
|
||||
public MongoDBBacking(LuckPermsPlugin plugin, DatastoreConfiguration configuration) {
|
||||
super(plugin, "MongoDB");
|
||||
this.configuration = configuration;
|
||||
}
|
@ -20,7 +20,7 @@
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package me.lucko.luckperms.common.storage.methods;
|
||||
package me.lucko.luckperms.common.storage.backing;
|
||||
|
||||
import com.zaxxer.hikari.HikariConfig;
|
||||
import com.zaxxer.hikari.HikariDataSource;
|
||||
@ -33,7 +33,7 @@ import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
|
||||
public class MySQLDatastore extends SQLDatastore {
|
||||
public class MySQLBacking extends SQLBacking {
|
||||
|
||||
private static final String CREATETABLE_UUID = "CREATE TABLE IF NOT EXISTS `lp_uuid` (`name` VARCHAR(16) NOT NULL, `uuid` VARCHAR(36) NOT NULL, PRIMARY KEY (`name`)) DEFAULT CHARSET=utf8;";
|
||||
private static final String CREATETABLE_USERS = "CREATE TABLE IF NOT EXISTS `lp_users` (`uuid` VARCHAR(36) NOT NULL, `name` VARCHAR(16) NOT NULL, `primary_group` VARCHAR(36) NOT NULL, `perms` TEXT NOT NULL, PRIMARY KEY (`uuid`)) DEFAULT CHARSET=utf8;";
|
||||
@ -44,7 +44,7 @@ public class MySQLDatastore extends SQLDatastore {
|
||||
private final DatastoreConfiguration configuration;
|
||||
private HikariDataSource hikari;
|
||||
|
||||
public MySQLDatastore(LuckPermsPlugin plugin, DatastoreConfiguration configuration) {
|
||||
public MySQLBacking(LuckPermsPlugin plugin, DatastoreConfiguration configuration) {
|
||||
super(plugin, "MySQL");
|
||||
this.configuration = configuration;
|
||||
}
|
@ -20,7 +20,7 @@
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package me.lucko.luckperms.common.storage.methods;
|
||||
package me.lucko.luckperms.common.storage.backing;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.reflect.TypeToken;
|
||||
@ -29,7 +29,6 @@ import me.lucko.luckperms.common.LuckPermsPlugin;
|
||||
import me.lucko.luckperms.common.data.Log;
|
||||
import me.lucko.luckperms.common.groups.Group;
|
||||
import me.lucko.luckperms.common.groups.GroupManager;
|
||||
import me.lucko.luckperms.common.storage.Datastore;
|
||||
import me.lucko.luckperms.common.tracks.Track;
|
||||
import me.lucko.luckperms.common.tracks.TrackManager;
|
||||
import me.lucko.luckperms.common.users.User;
|
||||
@ -44,7 +43,7 @@ import java.util.*;
|
||||
|
||||
import static me.lucko.luckperms.common.core.PermissionHolder.exportToLegacy;
|
||||
|
||||
abstract class SQLDatastore extends Datastore {
|
||||
abstract class SQLBacking extends AbstractBacking {
|
||||
private static final QueryPS EMPTY_PS = preparedStatement -> {};
|
||||
|
||||
private static final Type NM_TYPE = new TypeToken<Map<String, Boolean>>(){}.getType();
|
||||
@ -79,7 +78,7 @@ abstract class SQLDatastore extends Datastore {
|
||||
|
||||
private final Gson gson;
|
||||
|
||||
SQLDatastore(LuckPermsPlugin plugin, String name) {
|
||||
SQLBacking(LuckPermsPlugin plugin, String name) {
|
||||
super(plugin, name);
|
||||
gson = new Gson();
|
||||
}
|
@ -20,7 +20,7 @@
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package me.lucko.luckperms.common.storage.methods;
|
||||
package me.lucko.luckperms.common.storage.backing;
|
||||
|
||||
import lombok.Cleanup;
|
||||
import me.lucko.luckperms.common.LuckPermsPlugin;
|
||||
@ -28,7 +28,7 @@ import me.lucko.luckperms.common.LuckPermsPlugin;
|
||||
import java.io.File;
|
||||
import java.sql.*;
|
||||
|
||||
public class SQLiteDatastore extends SQLDatastore {
|
||||
public class SQLiteBacking extends SQLBacking {
|
||||
|
||||
private static final String CREATETABLE_UUID = "CREATE TABLE IF NOT EXISTS `lp_uuid` (`name` VARCHAR(16) NOT NULL, `uuid` VARCHAR(36) NOT NULL, PRIMARY KEY (`name`));";
|
||||
private static final String CREATETABLE_USERS = "CREATE TABLE IF NOT EXISTS `lp_users` (`uuid` VARCHAR(36) NOT NULL, `name` VARCHAR(16) NOT NULL, `primary_group` VARCHAR(36) NOT NULL, `perms` TEXT NOT NULL, PRIMARY KEY (`uuid`));";
|
||||
@ -40,7 +40,7 @@ public class SQLiteDatastore extends SQLDatastore {
|
||||
private Connection connection = null;
|
||||
private final Object connectionLock = new Object();
|
||||
|
||||
public SQLiteDatastore(LuckPermsPlugin plugin, File file) {
|
||||
public SQLiteBacking(LuckPermsPlugin plugin, File file) {
|
||||
super(plugin, "SQLite");
|
||||
this.file = file;
|
||||
}
|
@ -20,7 +20,7 @@
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package me.lucko.luckperms.common.storage.methods;
|
||||
package me.lucko.luckperms.common.storage.backing;
|
||||
|
||||
import lombok.Cleanup;
|
||||
import me.lucko.luckperms.common.LuckPermsPlugin;
|
||||
@ -42,8 +42,8 @@ import java.util.stream.Collectors;
|
||||
import static me.lucko.luckperms.common.core.PermissionHolder.exportToLegacy;
|
||||
|
||||
@SuppressWarnings({"unchecked", "ResultOfMethodCallIgnored"})
|
||||
public class YAMLDatastore extends FlatfileDatastore {
|
||||
public YAMLDatastore(LuckPermsPlugin plugin, File pluginDir) {
|
||||
public class YAMLBacking extends FlatfileBacking {
|
||||
public YAMLBacking(LuckPermsPlugin plugin, File pluginDir) {
|
||||
super(plugin, "Flatfile - YAML", pluginDir);
|
||||
}
|
||||
|
@ -41,7 +41,7 @@ public class AbstractListener {
|
||||
|
||||
final UuidCache cache = plugin.getUuidCache();
|
||||
if (!cache.isOnlineMode()) {
|
||||
UUID uuid = plugin.getDatastore().getUUID(username);
|
||||
UUID uuid = plugin.getDatastore().getUUID(username).getOrDefault(null);
|
||||
if (uuid != null) {
|
||||
cache.addToCache(u, uuid);
|
||||
} else {
|
||||
@ -51,7 +51,7 @@ public class AbstractListener {
|
||||
plugin.getDatastore().saveUUIDData(username, u, Callback.empty());
|
||||
}
|
||||
} else {
|
||||
UUID uuid = plugin.getDatastore().getUUID(username);
|
||||
UUID uuid = plugin.getDatastore().getUUID(username).getOrDefault(null);
|
||||
if (uuid == null) {
|
||||
plugin.getApiProvider().fireEventAsync(new UserFirstLoginEvent(u, username));
|
||||
}
|
||||
|
125
common/src/main/java/me/lucko/luckperms/common/utils/Buffer.java
Normal file
125
common/src/main/java/me/lucko/luckperms/common/utils/Buffer.java
Normal file
@ -0,0 +1,125 @@
|
||||
/*
|
||||
* Copyright (c) 2016 Lucko (Luck) <luck@lucko.me>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package me.lucko.luckperms.common.utils;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
import lombok.NonNull;
|
||||
import lombok.Setter;
|
||||
import me.lucko.luckperms.common.storage.AbstractFuture;
|
||||
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.ListIterator;
|
||||
|
||||
/**
|
||||
* Holds a buffer of objects to be processed after they've been in the buffer for a given time.
|
||||
* @param <T> the type of objects in the buffer
|
||||
* @param <R> the type of result produced by the final process
|
||||
*/
|
||||
public abstract class Buffer<T, R> implements Runnable {
|
||||
private static final long DEFAULT_FLUSH_TIME = 5000; // 5 seconds
|
||||
|
||||
private final List<BufferedObject<T, R>> buffer = new LinkedList<>();
|
||||
|
||||
public LPFuture<R> enqueue(@NonNull T t) {
|
||||
synchronized (buffer) {
|
||||
ListIterator<BufferedObject<T, R>> it = buffer.listIterator();
|
||||
|
||||
BufferedObject<T, R> o = null;
|
||||
|
||||
while (it.hasNext()) {
|
||||
BufferedObject<T, R> obj = it.next();
|
||||
|
||||
if (obj.getObject().equals(t)) {
|
||||
o = obj;
|
||||
it.remove();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (o == null) {
|
||||
o = new BufferedObject<>(System.currentTimeMillis(), t, new AbstractFuture<R>());
|
||||
} else {
|
||||
o.setBufferTime(System.currentTimeMillis());
|
||||
}
|
||||
|
||||
buffer.add(o);
|
||||
return o.getFuture();
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract R dequeue(T t);
|
||||
|
||||
public void flush(long flushTime) {
|
||||
long time = System.currentTimeMillis();
|
||||
|
||||
synchronized (buffer) {
|
||||
ListIterator<BufferedObject<T, R>> it = buffer.listIterator(buffer.size());
|
||||
|
||||
while (it.hasPrevious()) {
|
||||
BufferedObject<T, R> obj = it.previous();
|
||||
long bufferedTime = time - obj.getBufferTime();
|
||||
|
||||
if (bufferedTime > flushTime) {
|
||||
|
||||
// Flush
|
||||
R r = dequeue(obj.getObject());
|
||||
obj.getFuture().complete(r);
|
||||
it.remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
flush(DEFAULT_FLUSH_TIME);
|
||||
}
|
||||
|
||||
@AllArgsConstructor
|
||||
private static class BufferedObject<T, R> {
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
private long bufferTime;
|
||||
|
||||
@Getter
|
||||
private final T object;
|
||||
|
||||
@Getter
|
||||
private final AbstractFuture<R> future;
|
||||
|
||||
public boolean equals(Object o) {
|
||||
if (o == this) return true;
|
||||
if (!(o instanceof Buffer.BufferedObject)) return false;
|
||||
|
||||
final BufferedObject other = (BufferedObject) o;
|
||||
return this.getObject() == null ? other.getObject() == null : this.getObject().equals(other.getObject());
|
||||
}
|
||||
|
||||
public int hashCode() {
|
||||
return 59 + (this.getObject() == null ? 43 : this.getObject().hashCode());
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,128 @@
|
||||
/*
|
||||
* Copyright (c) 2016 Lucko (Luck) <luck@lucko.me>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package me.lucko.luckperms.common.utils;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import me.lucko.luckperms.common.storage.AbstractFuture;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.concurrent.Future;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
@RequiredArgsConstructor
|
||||
public abstract class BufferedRequest<T> {
|
||||
private final long bufferTimeMillis;
|
||||
private final Consumer<Runnable> executor;
|
||||
|
||||
private WeakReference<Processor<T>> processor = null;
|
||||
|
||||
@Getter
|
||||
private ReentrantLock lock = new ReentrantLock();
|
||||
|
||||
public Future<T> request() {
|
||||
lock.lock();
|
||||
try {
|
||||
if (processor != null) {
|
||||
Processor<T> p = processor.get();
|
||||
if (p != null && p.isUsable()) {
|
||||
return p.getAndExtend();
|
||||
}
|
||||
}
|
||||
|
||||
Processor<T> p = new Processor<>(bufferTimeMillis, this::perform);
|
||||
executor.accept(p);
|
||||
processor = new WeakReference<>(p);
|
||||
return p.get();
|
||||
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract T perform();
|
||||
|
||||
|
||||
@RequiredArgsConstructor
|
||||
private static class Processor<R> implements Runnable {
|
||||
private final long delayMillis;
|
||||
private final Supplier<R> supplier;
|
||||
|
||||
@Getter
|
||||
private boolean usable = true;
|
||||
|
||||
private final ReentrantLock lock = new ReentrantLock();
|
||||
private long executionTime;
|
||||
private final AbstractFuture<R> future = new AbstractFuture<>();
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
lock.lock();
|
||||
try {
|
||||
executionTime = System.currentTimeMillis() + delayMillis;
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
|
||||
while (true) {
|
||||
lock.lock();
|
||||
try {
|
||||
if (System.currentTimeMillis() > executionTime) {
|
||||
usable = false;
|
||||
break;
|
||||
}
|
||||
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
|
||||
try {
|
||||
Thread.sleep(500);
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
R result = supplier.get();
|
||||
future.complete(result);
|
||||
}
|
||||
|
||||
public Future<R> get() {
|
||||
return future;
|
||||
}
|
||||
|
||||
public Future<R> getAndExtend() {
|
||||
lock.lock();
|
||||
try {
|
||||
executionTime = System.currentTimeMillis() + delayMillis;
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
|
||||
return future;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,38 @@
|
||||
/*
|
||||
* Copyright (c) 2016 Lucko (Luck) <luck@lucko.me>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package me.lucko.luckperms.common.utils;
|
||||
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.Future;
|
||||
|
||||
public interface LPFuture<T> extends Future<T> {
|
||||
|
||||
default T getOrDefault(T def) {
|
||||
try {
|
||||
return get();
|
||||
} catch (InterruptedException | ExecutionException e) {
|
||||
return def;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -307,6 +307,11 @@ public class LPSpongePlugin implements LuckPermsPlugin {
|
||||
scheduler.createTaskBuilder().execute(r).submit(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doAsyncRepeating(Runnable r, long interval) {
|
||||
scheduler.createTaskBuilder().async().intervalTicks(interval).execute(r).submit(this);
|
||||
}
|
||||
|
||||
private void registerPermission(PermissionService p, String node) {
|
||||
Optional<PermissionDescription.Builder> builder = p.newDescriptionBuilder(this);
|
||||
if (!builder.isPresent()) return;
|
||||
|
Loading…
Reference in New Issue
Block a user