Changes for & release of API 2.14

This commit is contained in:
Luck 2016-11-12 14:10:42 +00:00
parent e9131f729a
commit 563dd4683d
No known key found for this signature in database
GPG Key ID: EFA9B3EC5FD90F8B
88 changed files with 872 additions and 850 deletions

View File

@ -5,7 +5,7 @@
<parent> <parent>
<artifactId>luckperms</artifactId> <artifactId>luckperms</artifactId>
<groupId>me.lucko.luckperms</groupId> <groupId>me.lucko.luckperms</groupId>
<version>2.13-SNAPSHOT</version> <version>2.14-SNAPSHOT</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>

View File

@ -29,226 +29,50 @@ import java.util.UUID;
/** /**
* Interface for the internal Datastore instance * Interface for the internal Datastore instance
* @deprecated as of version 2.14 in favour of {@link Storage}.
*/ */
@SuppressWarnings("unused") @Deprecated
public interface Datastore { public interface Datastore {
String getName(); String getName();
boolean isAcceptingLogins(); boolean isAcceptingLogins();
/** @Deprecated
* Gets the {@link Sync} interface.
*
* All operations through this interface are called immediately and in the same thread as they are called.
* Datastore operations are thread blocking, and Sync operations should not be called on the main server thread.
* @return the sync interface
*/
Sync sync(); Sync sync();
/** @Deprecated
* Gets the {@link Async} interface.
*
* All operations through this interface are called in a new, separate asynchronous thread.
* When the operation is complete, the provided callback method is called, in applicable, in the main server thread.
* @return the async interface
*/
Async async(); Async async();
/** @Deprecated
* Gets the {@link Future} interface.
*
* All operations through this interface are called in a new, separate asynchronous thread, similar to {@link Async}.
* The only difference is that instead of providing a callback, a {@link java.util.concurrent.Future} is returned.
* See the Oracle JavaDocs for usage of the Future class.
* @return the future interface
*/
Future future(); Future future();
/** @Deprecated
* All operations through this interface are called immediately and in the same thread as they are called.
* Datastore operations are thread blocking, and Sync operations should not be called on the main server thread.
*/
interface Sync { interface Sync {
/**
* Saves an action to the datastore
* @param entry the log entry to be saved
* @return true if the operation completed successfully.
* @throws NullPointerException if entry is null
*/
boolean logAction(LogEntry entry); boolean logAction(LogEntry entry);
/**
* Loads and returns the log from the datastore
* @return a log instance, could be null
*/
Log getLog(); Log getLog();
/**
* Either loads or creates a user object, and loads it into the plugins internal storage
* @param uuid the uuid of the user
* @param username the users username. (if you want to specify <code>null</code> here, just input "null" as a string.)
* @return true if the operation completed successfully.
* @throws NullPointerException if uuid or username is null
* @throws IllegalArgumentException if either of the parameters are invalid
* @deprecated functionality of this method is taken on by {@link #loadUser(UUID, String)}
*/
@Deprecated @Deprecated
boolean loadOrCreateUser(UUID uuid, String username); boolean loadOrCreateUser(UUID uuid, String username);
/**
* Loads a user from the datastore into the plugins internal storage.
* @param uuid the uuid of the user to load
* @return true if the user exists, and was loaded correctly.
* @throws NullPointerException if uuid is null
* @deprecated replaced by {@link #loadUser(UUID, String)}
*/
@Deprecated @Deprecated
boolean loadUser(UUID uuid); boolean loadUser(UUID uuid);
/**
* Loads a user's data into the plugins internal storage.
* @param uuid the uuid of the user to load
* @param username the users username. (if you want to specify <code>null</code> here, just input "null" as a string.)
* @return if the operation was performed successfully
* @throws NullPointerException if uuid or username is null
* @since 2.6
*/
boolean loadUser(UUID uuid, String username); boolean loadUser(UUID uuid, String username);
/**
* Saves a user object into the datastore. You should call this after you make any changes to a user.
* @param user the user to save
* @return true if the operation completed successfully.
* @throws NullPointerException if user is null
* @throws IllegalStateException if the user instance was not obtained from LuckPerms.
*/
boolean saveUser(User user); boolean saveUser(User user);
/**
* Removes users from the datastore who are "default". This is called every time the plugin loads.
* @return true if the operation completed successfully
* @since 2.6
*/
boolean cleanupUsers(); boolean cleanupUsers();
/**
* Gets a set all user's UUIDs who are "unique", and aren't just a member of the "default" group.
* @return a set of uuids, or null if the operation failed.
* @since 2.6
*/
Set<UUID> getUniqueUsers(); Set<UUID> getUniqueUsers();
/**
* Creates and loads a group into the plugins internal storage
* @param name the name of the group
* @return true if the operation completed successfully
* @throws NullPointerException if name is null
* @throws IllegalArgumentException if the name is invalid
*/
boolean createAndLoadGroup(String name); boolean createAndLoadGroup(String name);
/**
* Loads a group into the plugins internal storage.
* @param name the name of the group
* @return true if the operation completed successfully
* @throws NullPointerException if name is null
* @throws IllegalArgumentException if the name is invalid
*/
boolean loadGroup(String name); boolean loadGroup(String name);
/**
* Loads all groups from the datastore into the plugins internal storage
* @return true if the operation completed successfully.
*/
boolean loadAllGroups(); boolean loadAllGroups();
/**
* Saves a group back to the datastore. You should call this after you make any changes to a group.
* @param group the group to save
* @return true if the operation completed successfully.
* @throws NullPointerException if group is null
* @throws IllegalStateException if the group instance was not obtained from LuckPerms.
*/
boolean saveGroup(Group group); boolean saveGroup(Group group);
/**
* Permanently deletes a group from the datastore
* @param group the group to delete
* @return true if the operation completed successfully.
* @throws NullPointerException if group is null
* @throws IllegalStateException if the group instance was not obtained from LuckPerms.
*/
boolean deleteGroup(Group group); boolean deleteGroup(Group group);
/**
* Creates and loads a track into the plugins internal storage
* @param name the name of the track
* @return true if the operation completed successfully
* @throws NullPointerException if name is null
* @throws IllegalArgumentException if the name is invalid
*/
boolean createAndLoadTrack(String name); boolean createAndLoadTrack(String name);
/**
* Loads a track into the plugins internal storage.
* @param name the name of the track
* @return true if the operation completed successfully
* @throws NullPointerException if name is null
* @throws IllegalArgumentException if the name is invalid
*/
boolean loadTrack(String name); boolean loadTrack(String name);
/**
* Loads all tracks from the datastore into the plugins internal storage
* @return true if the operation completed successfully.
*/
boolean loadAllTracks(); boolean loadAllTracks();
/**
* Saves a track back to the datastore. You should call this after you make any changes to a track.
* @param track the track to save
* @return true if the operation completed successfully.
* @throws NullPointerException if track is null
* @throws IllegalStateException if the track instance was not obtained from LuckPerms.
*/
boolean saveTrack(Track track); boolean saveTrack(Track track);
/**
* Permanently deletes a track from the datastore
* @param track the track to delete
* @return true if the operation completed successfully.
* @throws NullPointerException if track is null
* @throws IllegalStateException if the track instance was not obtained from LuckPerms.
*/
boolean deleteTrack(Track track); boolean deleteTrack(Track track);
/**
* Saves UUID caching data to the datastore
* @param username the users username
* @param uuid the users mojang unique id
* @return true if the operation completed successfully.
* @throws NullPointerException if either parameters are null
* @throws IllegalArgumentException if the username is invalid
*/
boolean saveUUIDData(String username, UUID uuid); boolean saveUUIDData(String username, UUID uuid);
/**
* Gets a UUID from a username
* @param username the corresponding username
* @return a uuid object, could be null
* @throws NullPointerException if either parameters are null
* @throws IllegalArgumentException if the username is invalid
*/
UUID getUUID(String username); UUID getUUID(String username);
} }
/** @Deprecated
* All operations through this interface are called in a new, separate asynchronous thread.
* When the operation is complete, the provided callback method is called, in applicable, in the main server thread.
*
* See {@link Sync} for method documentation.
*/
interface Async { interface Async {
void logAction(LogEntry entry, Callback<Boolean> callback); void logAction(LogEntry entry, Callback<Boolean> callback);
void getLog(Callback<Log> callback); void getLog(Callback<Log> callback);
@ -274,13 +98,7 @@ public interface Datastore {
void getUUID(String username, Callback<UUID> callback); void getUUID(String username, Callback<UUID> callback);
} }
/** @Deprecated
* All operations through this interface are called in a new, separate asynchronous thread, similar to {@link Async}.
* The only difference is that instead of providing a callback, a {@link java.util.concurrent.Future} is returned.
* See the Oracle JavaDocs for usage of the Future class.
*
* See {@link Sync} for method documentation.
*/
interface Future { interface Future {
java.util.concurrent.Future<Boolean> logAction(LogEntry entry); java.util.concurrent.Future<Boolean> logAction(LogEntry entry);
java.util.concurrent.Future<Log> getLog(); java.util.concurrent.Future<Log> getLog();

View File

@ -109,7 +109,9 @@ public interface LPConfiguration {
/** /**
* @return true if permission checks are being recorded / debugged * @return true if permission checks are being recorded / debugged
* @since 2.9 * @since 2.9
* @deprecated as this value is now always false. Functionality was replaced by the verbose command.
*/ */
@Deprecated
boolean getDebugPermissionChecks(); boolean getDebugPermissionChecks();
/** /**

View File

@ -79,11 +79,27 @@ public interface LuckPermsApi {
LPConfiguration getConfiguration(); LPConfiguration getConfiguration();
/** /**
* Gets a wrapped {@link Datastore} instance, with somewhat limited access * Gets a wrapped {@link Storage} instance.
* @return a datastore instance * @return a storage instance
* @since 2.14
*/ */
Storage getStorage();
/**
* Gets a wrapped Datastore instance.
* @return a datastore instance
* @deprecated in favour of {@link #getStorage()}
*/
@SuppressWarnings("deprecation")
@Deprecated
Datastore getDatastore(); Datastore getDatastore();
/**
* Gets the messaging service in use on the platform, if present.
* @return an optional that may contain a messaging service instance.
*/
Optional<MessagingService> getMessagingService();
/** /**
* Gets the {@link Logger} wrapping used by the platform * Gets the {@link Logger} wrapping used by the platform
* @return the logger instance * @return the logger instance
@ -92,7 +108,7 @@ public interface LuckPermsApi {
/** /**
* Gets a wrapped {@link UuidCache} instance, providing read access to the LuckPerms internal uuid caching system * Gets a wrapped {@link UuidCache} instance, providing read access to the LuckPerms internal uuid caching system
* @return a uuidcache instance * @return a uuid cache instance
*/ */
UuidCache getUuidCache(); UuidCache getUuidCache();

View File

@ -20,16 +20,18 @@
* SOFTWARE. * SOFTWARE.
*/ */
package me.lucko.luckperms.common.utils; package me.lucko.luckperms.api;
import com.google.common.util.concurrent.Futures; /**
* Exposes any networking provider being used on the platform. e.g. Redis
* @since 2.14
*/
public interface MessagingService {
import java.util.concurrent.Future; /**
* Uses the messaging service to inform other servers about changes.
public interface LPFuture<T> extends Future<T> { * This will push the update asynchronously, and this method will return almost immediately.
*/
default T getUnchecked() { void pushUpdate();
return Futures.getUnchecked(this);
}
} }

View File

@ -0,0 +1,217 @@
/*
* 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.api;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Executor;
import java.util.function.Consumer;
/**
* Interface for the internal Storage instance
*
* All methods return {@link CompletableFuture}s, which will be populated with the result once the data has been loaded
* asynchronously. Care should be taken when using the methods to ensure that the main server thread is not blocked.
*
* Methods such as {@link CompletableFuture#get()} and equivalent should <strong>not</strong> be called on the main server thread.
* If you need to use the result of these operations on the main server thread, please register a callback using
* {@link CompletableFuture#thenAcceptAsync(Consumer, Executor)} and {@link #getSyncExecutor()}.
*
* @since 2.14
*/
public interface Storage {
/**
* Get the name of the storage implementation.
* @return the name of the implementation
*/
String getName();
/**
* Return whether the storage instance is allowing logins on the platform.
* @return true if logins are enabled
*/
boolean isAcceptingLogins();
/**
* Returns an executor which will run all passed runnables on the main server thread.
* @return an executor instance
*/
Executor getSyncExecutor();
/**
* Returns an executor which will run all passed runnables asynchronously using the platforms scheduler & thread pools.
* @return an executor instance
*/
Executor getAsyncExecutor();
/**
* Saves an action to storage
* @param entry the log entry to be saved
* @return true if the operation completed successfully.
* @throws NullPointerException if entry is null
*/
CompletableFuture<Boolean> logAction(LogEntry entry);
/**
* Loads and returns the entire log from storage
* @return a log instance, could be null if loading failed
*/
CompletableFuture<Log> getLog();
/**
* Loads a user's data from the main storage into the plugins local storage.
* @param uuid the uuid of the user to load
* @param username the users username. (if you want to specify <code>null</code> here, just input "null" as a string.)
* @return if the operation completed successfully
* @throws NullPointerException if uuid or username is null
*/
CompletableFuture<Boolean> loadUser(UUID uuid, String username);
/**
* Saves a user object back to storage. You should call this after you make any changes to a user.
* @param user the user to save
* @return true if the operation completed successfully.
* @throws NullPointerException if user is null
* @throws IllegalStateException if the user instance was not obtained from LuckPerms.
*/
CompletableFuture<Boolean> saveUser(User user);
/**
* Removes users from the main storage who are "default". This is called every time the plugin loads.
* @return true if the operation completed successfully
*/
CompletableFuture<Boolean> cleanupUsers();
/**
* Gets a set all "unique" user UUIDs.
* "Unique" meaning the user isn't just a member of the "default" group.
* @return a set of uuids, or null if the operation failed.
*/
CompletableFuture<Set<UUID>> getUniqueUsers();
/**
* Creates and loads a group into the plugins local storage
* @param name the name of the group
* @return true if the operation completed successfully
* @throws NullPointerException if name is null
* @throws IllegalArgumentException if the name is invalid
*/
CompletableFuture<Boolean> createAndLoadGroup(String name);
/**
* Loads a group into the plugins local storage.
* @param name the name of the group
* @return true if the operation completed successfully
* @throws NullPointerException if name is null
* @throws IllegalArgumentException if the name is invalid
*/
CompletableFuture<Boolean> loadGroup(String name);
/**
* Loads all groups from the storage into memory
* @return true if the operation completed successfully.
*/
CompletableFuture<Boolean> loadAllGroups();
/**
* Saves a group back to storage. You should call this after you make any changes to a group.
* @param group the group to save
* @return true if the operation completed successfully.
* @throws NullPointerException if group is null
* @throws IllegalStateException if the group instance was not obtained from LuckPerms.
*/
CompletableFuture<Boolean> saveGroup(Group group);
/**
* Permanently deletes a group from storage.
* @param group the group to delete
* @return true if the operation completed successfully.
* @throws NullPointerException if group is null
* @throws IllegalStateException if the group instance was not obtained from LuckPerms.
*/
CompletableFuture<Boolean> deleteGroup(Group group);
/**
* Creates and loads a track into the plugins local storage
* @param name the name of the track
* @return true if the operation completed successfully
* @throws NullPointerException if name is null
* @throws IllegalArgumentException if the name is invalid
*/
CompletableFuture<Boolean> createAndLoadTrack(String name);
/**
* Loads a track into the plugins local storage.
* @param name the name of the track
* @return true if the operation completed successfully
* @throws NullPointerException if name is null
* @throws IllegalArgumentException if the name is invalid
*/
CompletableFuture<Boolean> loadTrack(String name);
/**
* Loads all tracks from the storage into memory
* @return true if the operation completed successfully.
*/
CompletableFuture<Boolean> loadAllTracks();
/**
* Saves a track back to storage. You should call this after you make any changes to a track.
* @param track the track to save
* @return true if the operation completed successfully.
* @throws NullPointerException if track is null
* @throws IllegalStateException if the track instance was not obtained from LuckPerms.
*/
CompletableFuture<Boolean> saveTrack(Track track);
/**
* Permanently deletes a track from storage
* @param track the track to delete
* @return true if the operation completed successfully.
* @throws NullPointerException if track is null
* @throws IllegalStateException if the track instance was not obtained from LuckPerms.
*/
CompletableFuture<Boolean> deleteTrack(Track track);
/**
* Saves UUID caching data to the global cache
* @param username the users username
* @param uuid the users mojang unique id
* @return true if the operation completed successfully.
* @throws NullPointerException if either parameters are null
* @throws IllegalArgumentException if the username is invalid
*/
CompletableFuture<Boolean> saveUUIDData(String username, UUID uuid);
/**
* Gets a UUID from a username
* @param username the corresponding username
* @return a uuid object, could be null
* @throws NullPointerException if either parameters are null
* @throws IllegalArgumentException if the username is invalid
*/
CompletableFuture<UUID> getUUID(String username);
}

View File

@ -32,8 +32,8 @@ import java.util.UUID;
* they first join the server, but this UUID will then not be consistent across the network. LuckPerms will instead check * they first join the server, but this UUID will then not be consistent across the network. LuckPerms will instead check
* the datastore cache, to get a UUID for a user that is consistent across an entire network. * the datastore cache, to get a UUID for a user that is consistent across an entire network.
* *
* <p> If you want to get a user object from the datastore using the api on a server in offline mode, you will need to use this cache, * <p> If you want to get a user object from the Storage using the api on a server in offline mode, you will need to use this cache,
* OR use Datastore#getUUID, for users that are not online. * OR use Storage#getUUID, for users that are not online.
* *
* <p> WARNING: THIS IS ONLY EFFECTIVE FOR ONLINE PLAYERS. USE THE DATASTORE METHODS FOR OFFLINE PLAYERS. * <p> WARNING: THIS IS ONLY EFFECTIVE FOR ONLINE PLAYERS. USE THE DATASTORE METHODS FOR OFFLINE PLAYERS.
*/ */

View File

@ -28,7 +28,9 @@ import java.util.function.Consumer;
* A callback used to wait for the completion of asynchronous operations. * A callback used to wait for the completion of asynchronous operations.
* All callbacks are ran on the main server thread. * All callbacks are ran on the main server thread.
* @param <T> the return type * @param <T> the return type
* @deprecated in favour of {@link Consumer}
*/ */
@Deprecated
public interface Callback<T> { public interface Callback<T> {
/** /**
@ -55,4 +57,17 @@ public interface Callback<T> {
return consumer::accept; return consumer::accept;
} }
/**
* Helper method for converting old {@link Callback}s to use the new {@link me.lucko.luckperms.api.Storage} interface.
* @param callback the callback to convert
* @param <T> the return type
* @return a consumer instance
* @since 2.14
* @deprecated in favour of just using {@link Consumer}s.
*/
@Deprecated
static <T> Consumer<T> convertToConsumer(Callback<T> callback) {
return callback::onComplete;
}
} }

View File

@ -5,7 +5,7 @@
<parent> <parent>
<artifactId>luckperms</artifactId> <artifactId>luckperms</artifactId>
<groupId>me.lucko.luckperms</groupId> <groupId>me.lucko.luckperms</groupId>
<version>2.13-SNAPSHOT</version> <version>2.14-SNAPSHOT</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>

View File

@ -5,7 +5,7 @@
<parent> <parent>
<artifactId>luckperms</artifactId> <artifactId>luckperms</artifactId>
<groupId>me.lucko.luckperms</groupId> <groupId>me.lucko.luckperms</groupId>
<version>2.13-SNAPSHOT</version> <version>2.14-SNAPSHOT</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>

View File

@ -5,7 +5,7 @@
<parent> <parent>
<artifactId>luckperms</artifactId> <artifactId>luckperms</artifactId>
<groupId>me.lucko.luckperms</groupId> <groupId>me.lucko.luckperms</groupId>
<version>2.13-SNAPSHOT</version> <version>2.14-SNAPSHOT</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>

View File

@ -48,7 +48,7 @@ class BukkitListener extends AbstractListener implements Listener {
@EventHandler(priority = EventPriority.LOWEST) @EventHandler(priority = EventPriority.LOWEST)
public void onPlayerPreLogin(AsyncPlayerPreLoginEvent e) { public void onPlayerPreLogin(AsyncPlayerPreLoginEvent e) {
if (!plugin.isStarted() || !plugin.getDatastore().isAcceptingLogins()) { if (!plugin.isStarted() || !plugin.getStorage().isAcceptingLogins()) {
// The datastore is disabled, prevent players from joining the server // The datastore is disabled, prevent players from joining the server
e.disallow(AsyncPlayerPreLoginEvent.Result.KICK_OTHER, Message.LOADING_ERROR.toString()); e.disallow(AsyncPlayerPreLoginEvent.Result.KICK_OTHER, Message.LOADING_ERROR.toString());
@ -61,7 +61,7 @@ class BukkitListener extends AbstractListener implements Listener {
@EventHandler(priority = EventPriority.MONITOR) @EventHandler(priority = EventPriority.MONITOR)
public void onPlayerPreLoginMonitor(AsyncPlayerPreLoginEvent e) { public void onPlayerPreLoginMonitor(AsyncPlayerPreLoginEvent e) {
if (plugin.isStarted() && plugin.getDatastore().isAcceptingLogins() && e.getLoginResult() != AsyncPlayerPreLoginEvent.Result.ALLOWED) { if (plugin.isStarted() && plugin.getStorage().isAcceptingLogins() && e.getLoginResult() != AsyncPlayerPreLoginEvent.Result.ALLOWED) {
// Login event was cancelled by another plugin // Login event was cancelled by another plugin
onLeave(e.getUniqueId()); onLeave(e.getUniqueId());

View File

@ -49,7 +49,7 @@ import me.lucko.luckperms.common.groups.GroupManager;
import me.lucko.luckperms.common.messaging.RedisMessaging; import me.lucko.luckperms.common.messaging.RedisMessaging;
import me.lucko.luckperms.common.runnables.ExpireTemporaryTask; import me.lucko.luckperms.common.runnables.ExpireTemporaryTask;
import me.lucko.luckperms.common.runnables.UpdateTask; import me.lucko.luckperms.common.runnables.UpdateTask;
import me.lucko.luckperms.common.storage.Datastore; import me.lucko.luckperms.common.storage.Storage;
import me.lucko.luckperms.common.storage.StorageFactory; import me.lucko.luckperms.common.storage.StorageFactory;
import me.lucko.luckperms.common.tracks.TrackManager; import me.lucko.luckperms.common.tracks.TrackManager;
import me.lucko.luckperms.common.users.UserManager; import me.lucko.luckperms.common.users.UserManager;
@ -68,12 +68,16 @@ import org.bukkit.plugin.java.JavaPlugin;
import java.io.File; import java.io.File;
import java.util.*; import java.util.*;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Executor;
import java.util.concurrent.ExecutorService; import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors; import java.util.concurrent.Executors;
import java.util.stream.Collectors; import java.util.stream.Collectors;
@Getter @Getter
public class LPBukkitPlugin extends JavaPlugin implements LuckPermsPlugin { public class LPBukkitPlugin extends JavaPlugin implements LuckPermsPlugin {
private ExecutorService executorService;
private Executor syncExecutor;
private Executor asyncExecutor;
private VaultHook vaultHook = null; private VaultHook vaultHook = null;
private final Set<UUID> ignoringLogs = ConcurrentHashMap.newKeySet(); private final Set<UUID> ignoringLogs = ConcurrentHashMap.newKeySet();
@ -81,7 +85,7 @@ public class LPBukkitPlugin extends JavaPlugin implements LuckPermsPlugin {
private UserManager userManager; private UserManager userManager;
private GroupManager groupManager; private GroupManager groupManager;
private TrackManager trackManager; private TrackManager trackManager;
private Datastore datastore; private Storage storage;
private RedisMessaging redisMessaging = null; private RedisMessaging redisMessaging = null;
private UuidCache uuidCache; private UuidCache uuidCache;
private ApiProvider apiProvider; private ApiProvider apiProvider;
@ -99,13 +103,12 @@ public class LPBukkitPlugin extends JavaPlugin implements LuckPermsPlugin {
private DebugHandler debugHandler; private DebugHandler debugHandler;
private BukkitSenderFactory senderFactory; private BukkitSenderFactory senderFactory;
private ExecutorService executorService;
private boolean schedulerAvailable = false;
@Override @Override
public void onEnable() { public void onEnable() {
// Used whilst the server is still starting // Used whilst the server is still starting
executorService = Executors.newCachedThreadPool(); executorService = Executors.newCachedThreadPool();
asyncExecutor = executorService;
syncExecutor = r -> getServer().getScheduler().runTask(this, r);
log = LogFactory.wrap(getLogger()); log = LogFactory.wrap(getLogger());
debugHandler = new DebugHandler(); debugHandler = new DebugHandler();
@ -129,7 +132,7 @@ public class LPBukkitPlugin extends JavaPlugin implements LuckPermsPlugin {
pm.registerEvents(new BukkitListener(this), this); pm.registerEvents(new BukkitListener(this), this);
// initialise datastore // initialise datastore
datastore = StorageFactory.getDatastore(this, "h2"); storage = StorageFactory.getInstance(this, "h2");
// initialise redis // initialise redis
if (getConfiguration().isRedisEnabled()) { if (getConfiguration().isRedisEnabled()) {
@ -236,10 +239,9 @@ public class LPBukkitPlugin extends JavaPlugin implements LuckPermsPlugin {
getServer().getOperators().forEach(o -> o.setOp(false)); getServer().getOperators().forEach(o -> o.setOp(false));
} }
// shutdown the temporary executor when the Bukkit one starts // replace the temporary executor when the Bukkit one starts
getServer().getScheduler().runTaskAsynchronously(this, () -> { getServer().getScheduler().runTaskAsynchronously(this, () -> {
schedulerAvailable = true; asyncExecutor = r -> getServer().getScheduler().runTaskAsynchronously(this, r);
executorService.shutdown();
}); });
started = true; started = true;
@ -250,7 +252,7 @@ public class LPBukkitPlugin extends JavaPlugin implements LuckPermsPlugin {
public void onDisable() { public void onDisable() {
started = false; started = false;
getLog().info("Closing datastore..."); getLog().info("Closing datastore...");
datastore.shutdown(); storage.shutdown();
if (redisMessaging != null) { if (redisMessaging != null) {
getLog().info("Closing redis..."); getLog().info("Closing redis...");
@ -268,16 +270,12 @@ public class LPBukkitPlugin extends JavaPlugin implements LuckPermsPlugin {
@Override @Override
public void doAsync(Runnable r) { public void doAsync(Runnable r) {
if (!schedulerAvailable) { asyncExecutor.execute(r);
executorService.submit(r);
} else {
getServer().getScheduler().runTaskAsynchronously(this, r);
}
} }
@Override @Override
public void doSync(Runnable r) { public void doSync(Runnable r) {
getServer().getScheduler().runTask(this, r); syncExecutor.execute(r);
} }
@Override @Override

View File

@ -122,7 +122,7 @@ public class MigrationBPermissions extends SubCommand<Object> {
} }
// Make a LuckPerms group for the one being migrated. // Make a LuckPerms group for the one being migrated.
plugin.getDatastore().createAndLoadGroup(groupName).getUnchecked(); plugin.getStorage().createAndLoadGroup(groupName).join();
me.lucko.luckperms.common.groups.Group lpGroup = plugin.getGroupManager().get(groupName); me.lucko.luckperms.common.groups.Group lpGroup = plugin.getGroupManager().get(groupName);
try { try {
LogEntry.build() LogEntry.build()
@ -134,7 +134,7 @@ public class MigrationBPermissions extends SubCommand<Object> {
} }
migrateHolder(plugin, world, group, lpGroup); migrateHolder(plugin, world, group, lpGroup);
plugin.getDatastore().saveGroup(lpGroup); plugin.getStorage().saveGroup(lpGroup);
} }
log.info("bPermissions Migration: Migrated " + groupCount + " groups in world " + world.getName() + "."); log.info("bPermissions Migration: Migrated " + groupCount + " groups in world " + world.getName() + ".");
@ -158,12 +158,12 @@ public class MigrationBPermissions extends SubCommand<Object> {
} }
// Make a LuckPerms user for the one being migrated. // Make a LuckPerms user for the one being migrated.
plugin.getDatastore().loadUser(uuid, "null").getUnchecked(); plugin.getStorage().loadUser(uuid, "null").join();
me.lucko.luckperms.common.users.User lpUser = plugin.getUserManager().get(uuid); me.lucko.luckperms.common.users.User lpUser = plugin.getUserManager().get(uuid);
migrateHolder(plugin, world, user, lpUser); migrateHolder(plugin, world, user, lpUser);
plugin.getDatastore().saveUser(lpUser); plugin.getStorage().saveUser(lpUser);
plugin.getUserManager().cleanup(lpUser); plugin.getUserManager().cleanup(lpUser);
} }

View File

@ -72,7 +72,7 @@ public class MigrationGroupManager extends SubCommand<Object> {
GlobalGroups gg = GroupManager.getGlobalGroups(); GlobalGroups gg = GroupManager.getGlobalGroups();
for (Group g : gg.getGroupList()) { for (Group g : gg.getGroupList()) {
plugin.getDatastore().createAndLoadGroup(g.getName().toLowerCase()).getUnchecked(); plugin.getStorage().createAndLoadGroup(g.getName().toLowerCase()).join();
me.lucko.luckperms.common.groups.Group group = plugin.getGroupManager().get(g.getName().toLowerCase()); me.lucko.luckperms.common.groups.Group group = plugin.getGroupManager().get(g.getName().toLowerCase());
try { try {
LogEntry.build() LogEntry.build()
@ -120,7 +120,7 @@ public class MigrationGroupManager extends SubCommand<Object> {
} }
} }
plugin.getDatastore().saveGroup(group); plugin.getStorage().saveGroup(group);
} }
Map<UUID, Map<Map.Entry<String, String>, Boolean>> users = new HashMap<>(); Map<UUID, Map<Map.Entry<String, String>, Boolean>> users = new HashMap<>();
@ -195,7 +195,7 @@ public class MigrationGroupManager extends SubCommand<Object> {
log.info("GroupManager Migration: Found a total of " + users.size() + " users and " + groups.size() + " groups."); log.info("GroupManager Migration: Found a total of " + users.size() + " users and " + groups.size() + " groups.");
for (Map.Entry<String, Map<Map.Entry<String, String>, Boolean>> e : groups.entrySet()) { for (Map.Entry<String, Map<Map.Entry<String, String>, Boolean>> e : groups.entrySet()) {
plugin.getDatastore().createAndLoadGroup(e.getKey()).getUnchecked(); plugin.getStorage().createAndLoadGroup(e.getKey()).join();
me.lucko.luckperms.common.groups.Group group = plugin.getGroupManager().get(e.getKey()); me.lucko.luckperms.common.groups.Group group = plugin.getGroupManager().get(e.getKey());
try { try {
LogEntry.build() LogEntry.build()
@ -234,11 +234,11 @@ public class MigrationGroupManager extends SubCommand<Object> {
} }
} }
plugin.getDatastore().saveGroup(group); plugin.getStorage().saveGroup(group);
} }
for (Map.Entry<UUID, Map<Map.Entry<String, String>, Boolean>> e : users.entrySet()) { for (Map.Entry<UUID, Map<Map.Entry<String, String>, Boolean>> e : users.entrySet()) {
plugin.getDatastore().loadUser(e.getKey(), "null").getUnchecked(); plugin.getStorage().loadUser(e.getKey(), "null").join();
me.lucko.luckperms.common.users.User user = plugin.getUserManager().get(e.getKey()); me.lucko.luckperms.common.users.User user = plugin.getUserManager().get(e.getKey());
for (Map.Entry<Map.Entry<String, String>, Boolean> n : e.getValue().entrySet()) { for (Map.Entry<Map.Entry<String, String>, Boolean> n : e.getValue().entrySet()) {
@ -279,7 +279,7 @@ public class MigrationGroupManager extends SubCommand<Object> {
} catch (ObjectLacksException ignored) {} } catch (ObjectLacksException ignored) {}
} }
plugin.getDatastore().saveUser(user); plugin.getStorage().saveUser(user);
plugin.getUserManager().cleanup(user); plugin.getUserManager().cleanup(user);
} }

View File

@ -100,7 +100,7 @@ public class MigrationPermissionsEx extends SubCommand<Object> {
maxGroupWeight = Math.max(maxGroupWeight, groupWeight); maxGroupWeight = Math.max(maxGroupWeight, groupWeight);
final String name = group.getName().toLowerCase(); final String name = group.getName().toLowerCase();
plugin.getDatastore().createAndLoadGroup(name).getUnchecked(); plugin.getStorage().createAndLoadGroup(name).join();
Group lpGroup = plugin.getGroupManager().get(name); Group lpGroup = plugin.getGroupManager().get(name);
try { try {
LogEntry.build() LogEntry.build()
@ -224,7 +224,7 @@ public class MigrationPermissionsEx extends SubCommand<Object> {
} }
} }
plugin.getDatastore().saveGroup(lpGroup); plugin.getStorage().saveGroup(lpGroup);
} }
@ -252,7 +252,7 @@ public class MigrationPermissionsEx extends SubCommand<Object> {
} }
userCount++; userCount++;
plugin.getDatastore().loadUser(u, "null").getUnchecked(); plugin.getStorage().loadUser(u, "null").join();
User lpUser = plugin.getUserManager().get(u); User lpUser = plugin.getUserManager().get(u);
try { try {
@ -385,7 +385,7 @@ public class MigrationPermissionsEx extends SubCommand<Object> {
} }
plugin.getUserManager().cleanup(lpUser); plugin.getUserManager().cleanup(lpUser);
plugin.getDatastore().saveUser(lpUser); plugin.getStorage().saveUser(lpUser);
} }
log.info("PermissionsEx Migration: Migrated " + userCount + " users."); log.info("PermissionsEx Migration: Migrated " + userCount + " users.");

View File

@ -251,7 +251,7 @@ public class MigrationPowerfulPerms extends SubCommand<Object> {
log.info("PowerfulPerms Migration: Starting group migration."); log.info("PowerfulPerms Migration: Starting group migration.");
Map<Integer, Group> groups = pm.getGroups(); // All versions Map<Integer, Group> groups = pm.getGroups(); // All versions
for (Group g : groups.values()) { for (Group g : groups.values()) {
plugin.getDatastore().createAndLoadGroup(g.getName().toLowerCase()).getUnchecked(); plugin.getStorage().createAndLoadGroup(g.getName().toLowerCase()).join();
final me.lucko.luckperms.common.groups.Group group = plugin.getGroupManager().get(g.getName().toLowerCase()); final me.lucko.luckperms.common.groups.Group group = plugin.getGroupManager().get(g.getName().toLowerCase());
try { try {
LogEntry.build() LogEntry.build()
@ -280,7 +280,7 @@ public class MigrationPowerfulPerms extends SubCommand<Object> {
} }
} }
plugin.getDatastore().saveGroup(group); plugin.getStorage().saveGroup(group);
} }
log.info("PowerfulPerms Migration: Group migration complete."); log.info("PowerfulPerms Migration: Group migration complete.");
@ -293,7 +293,7 @@ public class MigrationPowerfulPerms extends SubCommand<Object> {
progress.put(uuid, new CountDownLatch(2)); progress.put(uuid, new CountDownLatch(2));
// Create a LuckPerms user for the UUID // Create a LuckPerms user for the UUID
plugin.getDatastore().loadUser(uuid, "null").getUnchecked(); plugin.getStorage().loadUser(uuid, "null").join();
User user = plugin.getUserManager().get(uuid); User user = plugin.getUserManager().get(uuid);
// Get a list of Permissions held by the user from the PP API. // Get a list of Permissions held by the user from the PP API.
@ -304,7 +304,7 @@ public class MigrationPowerfulPerms extends SubCommand<Object> {
synchronized (progress) { synchronized (progress) {
progress.get(uuid).countDown(); progress.get(uuid).countDown();
if (progress.get(uuid).getCount() == 0) { if (progress.get(uuid).getCount() == 0) {
plugin.getDatastore().saveUser(user); plugin.getStorage().saveUser(user);
plugin.getUserManager().cleanup(user); plugin.getUserManager().cleanup(user);
} }
} }
@ -427,7 +427,7 @@ public class MigrationPowerfulPerms extends SubCommand<Object> {
synchronized (progress) { synchronized (progress) {
progress.get(uuid).countDown(); progress.get(uuid).countDown();
if (progress.get(uuid).getCount() == 0) { if (progress.get(uuid).getCount() == 0) {
plugin.getDatastore().saveUser(user); plugin.getStorage().saveUser(user);
plugin.getUserManager().cleanup(user); plugin.getUserManager().cleanup(user);
} }
} }

View File

@ -73,7 +73,7 @@ public class MigrationZPermissions extends SubCommand<Object> {
// Migrate all groups // Migrate all groups
log.info("zPermissions Migration: Starting group migration."); log.info("zPermissions Migration: Starting group migration.");
for (String g : service.getAllGroups()) { for (String g : service.getAllGroups()) {
plugin.getDatastore().createAndLoadGroup(g.toLowerCase()).getUnchecked(); plugin.getStorage().createAndLoadGroup(g.toLowerCase()).join();
Group group = plugin.getGroupManager().get(g.toLowerCase()); Group group = plugin.getGroupManager().get(g.toLowerCase());
try { try {
LogEntry.build() LogEntry.build()
@ -116,13 +116,13 @@ public class MigrationZPermissions extends SubCommand<Object> {
} }
} }
plugin.getDatastore().saveGroup(group); plugin.getStorage().saveGroup(group);
} }
// Migrate all tracks // Migrate all tracks
log.info("zPermissions Migration: Starting track migration."); log.info("zPermissions Migration: Starting track migration.");
for (String t : service.getAllTracks()) { for (String t : service.getAllTracks()) {
plugin.getDatastore().createAndLoadTrack(t.toLowerCase()).getUnchecked(); plugin.getStorage().createAndLoadTrack(t.toLowerCase()).join();
Track track = plugin.getTrackManager().get(t.toLowerCase()); Track track = plugin.getTrackManager().get(t.toLowerCase());
try { try {
LogEntry.build() LogEntry.build()
@ -145,13 +145,13 @@ public class MigrationZPermissions extends SubCommand<Object> {
} }
} }
plugin.getDatastore().saveTrack(track); plugin.getStorage().saveTrack(track);
} }
// Migrate all users. // Migrate all users.
log.info("zPermissions Migration: Starting user migration."); log.info("zPermissions Migration: Starting user migration.");
for (UUID u : service.getAllPlayersUUID()) { for (UUID u : service.getAllPlayersUUID()) {
plugin.getDatastore().loadUser(u, "null").getUnchecked(); plugin.getStorage().loadUser(u, "null").join();
User user = plugin.getUserManager().get(u); User user = plugin.getUserManager().get(u);
for (Map.Entry<String, Boolean> e : service.getPlayerPermissions(null, null, u).entrySet()) { for (Map.Entry<String, Boolean> e : service.getPlayerPermissions(null, null, u).entrySet()) {
@ -244,7 +244,7 @@ public class MigrationZPermissions extends SubCommand<Object> {
} }
plugin.getUserManager().cleanup(user); plugin.getUserManager().cleanup(user);
plugin.getDatastore().saveUser(user); plugin.getStorage().saveUser(user);
} }
log.info("zPermissions Migration: Success! Completed without any errors."); log.info("zPermissions Migration: Success! Completed without any errors.");

View File

@ -82,7 +82,7 @@ public class VaultPermissionHook extends Permission {
@Override @Override
public boolean isEnabled() { public boolean isEnabled() {
return plugin.getDatastore().isAcceptingLogins(); return plugin.getStorage().isAcceptingLogins();
} }
@Override @Override
@ -132,13 +132,12 @@ public class VaultPermissionHook extends Permission {
*/ */
void save(PermissionHolder holder) { void save(PermissionHolder holder) {
if (holder instanceof User) { if (holder instanceof User) {
plugin.getStorage().saveUser(((User) holder))
plugin.getDatastore().saveUser(((User) holder), b -> { .thenRunAsync(() -> ((User) holder).getRefreshBuffer().request(), plugin.getAsyncExecutor());
((User) holder).getRefreshBuffer().request();
});
} }
if (holder instanceof Group) { if (holder instanceof Group) {
plugin.getDatastore().saveGroup(((Group) holder), b -> plugin.getUpdateTaskBuffer().request()); plugin.getStorage().saveGroup(((Group) holder))
.thenRunAsync(() -> plugin.getUpdateTaskBuffer().request(), plugin.getAsyncExecutor());
} }
} }

View File

@ -5,7 +5,7 @@
<parent> <parent>
<artifactId>luckperms</artifactId> <artifactId>luckperms</artifactId>
<groupId>me.lucko.luckperms</groupId> <groupId>me.lucko.luckperms</groupId>
<version>2.13-SNAPSHOT</version> <version>2.14-SNAPSHOT</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>

View File

@ -96,28 +96,28 @@ public class BungeeListener extends AbstractListener implements Listener {
final PendingConnection c = e.getConnection(); final PendingConnection c = e.getConnection();
if (!cache.isOnlineMode()) { if (!cache.isOnlineMode()) {
UUID uuid = plugin.getDatastore().getUUID(c.getName()).getUnchecked(); UUID uuid = plugin.getStorage().getUUID(c.getName()).join();
if (uuid != null) { if (uuid != null) {
cache.addToCache(c.getUniqueId(), uuid); cache.addToCache(c.getUniqueId(), uuid);
} else { } else {
// No previous data for this player // No previous data for this player
plugin.getApiProvider().fireEventAsync(new UserFirstLoginEvent(c.getUniqueId(), c.getName())); plugin.getApiProvider().fireEventAsync(new UserFirstLoginEvent(c.getUniqueId(), c.getName()));
cache.addToCache(c.getUniqueId(), c.getUniqueId()); cache.addToCache(c.getUniqueId(), c.getUniqueId());
plugin.getDatastore().force().saveUUIDData(c.getName(), c.getUniqueId()).getUnchecked(); plugin.getStorage().force().saveUUIDData(c.getName(), c.getUniqueId()).join();
} }
} else { } else {
UUID uuid = plugin.getDatastore().getUUID(c.getName()).getUnchecked(); UUID uuid = plugin.getStorage().getUUID(c.getName()).join();
if (uuid == null) { if (uuid == null) {
plugin.getApiProvider().fireEventAsync(new UserFirstLoginEvent(c.getUniqueId(), c.getName())); plugin.getApiProvider().fireEventAsync(new UserFirstLoginEvent(c.getUniqueId(), c.getName()));
} }
// Online mode, no cache needed. This is just for name -> uuid lookup. // Online mode, no cache needed. This is just for name -> uuid lookup.
plugin.getDatastore().force().saveUUIDData(c.getName(), c.getUniqueId()).getUnchecked(); plugin.getStorage().force().saveUUIDData(c.getName(), c.getUniqueId()).join();
} }
// We have to make a new user on this thread whilst the connection is being held, or we get concurrency issues as the Bukkit server // We have to make a new user on this thread whilst the connection is being held, or we get concurrency issues as the Bukkit server
// and the BungeeCord server try to make a new user at the same time. // and the BungeeCord server try to make a new user at the same time.
plugin.getDatastore().force().loadUser(cache.getUUID(c.getUniqueId()), c.getName()).getUnchecked(); plugin.getStorage().force().loadUser(cache.getUUID(c.getUniqueId()), c.getName()).join();
User user = plugin.getUserManager().get(cache.getUUID(c.getUniqueId())); User user = plugin.getUserManager().get(cache.getUUID(c.getUniqueId()));
if (user == null) { if (user == null) {
plugin.getLog().warn("Failed to load user: " + c.getName()); plugin.getLog().warn("Failed to load user: " + c.getName());

View File

@ -44,7 +44,7 @@ import me.lucko.luckperms.common.groups.GroupManager;
import me.lucko.luckperms.common.messaging.RedisMessaging; import me.lucko.luckperms.common.messaging.RedisMessaging;
import me.lucko.luckperms.common.runnables.ExpireTemporaryTask; import me.lucko.luckperms.common.runnables.ExpireTemporaryTask;
import me.lucko.luckperms.common.runnables.UpdateTask; import me.lucko.luckperms.common.runnables.UpdateTask;
import me.lucko.luckperms.common.storage.Datastore; import me.lucko.luckperms.common.storage.Storage;
import me.lucko.luckperms.common.storage.StorageFactory; import me.lucko.luckperms.common.storage.StorageFactory;
import me.lucko.luckperms.common.tracks.TrackManager; import me.lucko.luckperms.common.tracks.TrackManager;
import me.lucko.luckperms.common.users.UserManager; import me.lucko.luckperms.common.users.UserManager;
@ -62,17 +62,20 @@ import java.util.List;
import java.util.Set; import java.util.Set;
import java.util.UUID; import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Executor;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors; import java.util.stream.Collectors;
@Getter @Getter
public class LPBungeePlugin extends Plugin implements LuckPermsPlugin { public class LPBungeePlugin extends Plugin implements LuckPermsPlugin {
private Executor executor;
private final Set<UUID> ignoringLogs = ConcurrentHashMap.newKeySet(); private final Set<UUID> ignoringLogs = ConcurrentHashMap.newKeySet();
private LPConfiguration configuration; private LPConfiguration configuration;
private UserManager userManager; private UserManager userManager;
private GroupManager groupManager; private GroupManager groupManager;
private TrackManager trackManager; private TrackManager trackManager;
private Datastore datastore; private Storage storage;
private RedisMessaging redisMessaging = null; private RedisMessaging redisMessaging = null;
private UuidCache uuidCache; private UuidCache uuidCache;
private ApiProvider apiProvider; private ApiProvider apiProvider;
@ -88,6 +91,7 @@ public class LPBungeePlugin extends Plugin implements LuckPermsPlugin {
@Override @Override
public void onEnable() { public void onEnable() {
executor = r -> getProxy().getScheduler().runAsync(this, r);
log = LogFactory.wrap(getLogger()); log = LogFactory.wrap(getLogger());
debugHandler = new DebugHandler(); debugHandler = new DebugHandler();
senderFactory = new BungeeSenderFactory(this); senderFactory = new BungeeSenderFactory(this);
@ -99,7 +103,7 @@ public class LPBungeePlugin extends Plugin implements LuckPermsPlugin {
getProxy().getPluginManager().registerListener(this, new BungeeListener(this)); getProxy().getPluginManager().registerListener(this, new BungeeListener(this));
// initialise datastore // initialise datastore
datastore = StorageFactory.getDatastore(this, "h2"); storage = StorageFactory.getInstance(this, "h2");
// initialise redis // initialise redis
if (getConfiguration().isRedisEnabled()) { if (getConfiguration().isRedisEnabled()) {
@ -183,7 +187,7 @@ public class LPBungeePlugin extends Plugin implements LuckPermsPlugin {
@Override @Override
public void onDisable() { public void onDisable() {
getLog().info("Closing datastore..."); getLog().info("Closing datastore...");
datastore.shutdown(); storage.shutdown();
if (redisMessaging != null) { if (redisMessaging != null) {
getLog().info("Closing redis..."); getLog().info("Closing redis...");
@ -300,7 +304,17 @@ public class LPBungeePlugin extends Plugin implements LuckPermsPlugin {
@Override @Override
public void doSync(Runnable r) { public void doSync(Runnable r) {
r.run(); doAsync(r);
}
@Override
public Executor getSyncExecutor() {
return executor;
}
@Override
public Executor getAsyncExecutor() {
return executor;
} }
@Override @Override

View File

@ -64,7 +64,7 @@ public class MigrationBungeePerms extends SubCommand<Object> {
groupCount++; groupCount++;
// Make a LuckPerms group for the one being migrated // Make a LuckPerms group for the one being migrated
plugin.getDatastore().createAndLoadGroup(g.getName().toLowerCase()).getUnchecked(); plugin.getStorage().createAndLoadGroup(g.getName().toLowerCase()).join();
me.lucko.luckperms.common.groups.Group group = plugin.getGroupManager().get(g.getName().toLowerCase()); me.lucko.luckperms.common.groups.Group group = plugin.getGroupManager().get(g.getName().toLowerCase());
try { try {
LogEntry.build() LogEntry.build()
@ -174,7 +174,7 @@ public class MigrationBungeePerms extends SubCommand<Object> {
} }
} }
plugin.getDatastore().saveGroup(group); plugin.getStorage().saveGroup(group);
} }
log.info("BungeePerms Migration: Migrated " + groupCount + " groups"); log.info("BungeePerms Migration: Migrated " + groupCount + " groups");
@ -188,7 +188,7 @@ public class MigrationBungeePerms extends SubCommand<Object> {
userCount++; userCount++;
// Make a LuckPerms user for the one being migrated. // Make a LuckPerms user for the one being migrated.
plugin.getDatastore().loadUser(u.getUUID(), "null").getUnchecked(); plugin.getStorage().loadUser(u.getUUID(), "null").join();
me.lucko.luckperms.common.users.User user = plugin.getUserManager().get(u.getUUID()); me.lucko.luckperms.common.users.User user = plugin.getUserManager().get(u.getUUID());
// Migrate global perms // Migrate global perms
@ -289,7 +289,7 @@ public class MigrationBungeePerms extends SubCommand<Object> {
} }
} }
plugin.getDatastore().saveUser(user); plugin.getStorage().saveUser(user);
plugin.getUserManager().cleanup(user); plugin.getUserManager().cleanup(user);
} }

View File

@ -5,7 +5,7 @@
<parent> <parent>
<artifactId>luckperms</artifactId> <artifactId>luckperms</artifactId>
<groupId>me.lucko.luckperms</groupId> <groupId>me.lucko.luckperms</groupId>
<version>2.13-SNAPSHOT</version> <version>2.14-SNAPSHOT</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>

View File

@ -36,7 +36,7 @@ import me.lucko.luckperms.common.core.UuidCache;
import me.lucko.luckperms.common.data.Importer; import me.lucko.luckperms.common.data.Importer;
import me.lucko.luckperms.common.groups.GroupManager; import me.lucko.luckperms.common.groups.GroupManager;
import me.lucko.luckperms.common.messaging.RedisMessaging; import me.lucko.luckperms.common.messaging.RedisMessaging;
import me.lucko.luckperms.common.storage.Datastore; import me.lucko.luckperms.common.storage.Storage;
import me.lucko.luckperms.common.tracks.TrackManager; import me.lucko.luckperms.common.tracks.TrackManager;
import me.lucko.luckperms.common.users.UserManager; import me.lucko.luckperms.common.users.UserManager;
import me.lucko.luckperms.common.utils.BufferedRequest; import me.lucko.luckperms.common.utils.BufferedRequest;
@ -47,6 +47,7 @@ import java.io.File;
import java.util.List; import java.util.List;
import java.util.Set; import java.util.Set;
import java.util.UUID; import java.util.UUID;
import java.util.concurrent.Executor;
/** /**
* Main internal interface for LuckPerms plugins, providing the base for abstraction throughout the project. * Main internal interface for LuckPerms plugins, providing the base for abstraction throughout the project.
@ -80,10 +81,10 @@ public interface LuckPermsPlugin {
LPConfiguration getConfiguration(); LPConfiguration getConfiguration();
/** /**
* Gets the primary datastore instance. This is likely to be wrapped with extra layers for caching, etc. * Gets the primary data storage instance. This is likely to be wrapped with extra layers for caching, etc.
* @return the datastore * @return the storage handler instance
*/ */
Datastore getDatastore(); Storage getStorage();
/** /**
* Gets the redis messaging instance if present. Could return null if redis is not enabled. * Gets the redis messaging instance if present. Could return null if redis is not enabled.
@ -158,6 +159,9 @@ public interface LuckPermsPlugin {
*/ */
void doSync(Runnable r); void doSync(Runnable r);
Executor getSyncExecutor();
Executor getAsyncExecutor();
/** /**
* Execute a runnable asynchronously on a loop * Execute a runnable asynchronously on a loop
* @param r the task to run * @param r the task to run

View File

@ -71,7 +71,7 @@ public class ApiProvider implements LuckPermsApi {
@Override @Override
public double getApiVersion() { public double getApiVersion() {
return 2.13; return 2.14;
} }
@Override @Override
@ -99,9 +99,20 @@ public class ApiProvider implements LuckPermsApi {
return new LPConfigurationLink(plugin.getConfiguration()); return new LPConfigurationLink(plugin.getConfiguration());
} }
@Override
public Storage getStorage() {
return new StorageLink(plugin, plugin.getStorage());
}
@SuppressWarnings("deprecation")
@Override @Override
public Datastore getDatastore() { public Datastore getDatastore() {
return new DatastoreLink(plugin, plugin.getDatastore()); return new DatastoreLink(plugin, plugin.getStorage());
}
@Override
public Optional<MessagingService> getMessagingService() {
return Optional.ofNullable(plugin.getRedisMessaging());
} }
@Override @Override

View File

@ -27,26 +27,29 @@ import lombok.NonNull;
import me.lucko.luckperms.api.*; import me.lucko.luckperms.api.*;
import me.lucko.luckperms.api.data.Callback; import me.lucko.luckperms.api.data.Callback;
import me.lucko.luckperms.common.LuckPermsPlugin; import me.lucko.luckperms.common.LuckPermsPlugin;
import me.lucko.luckperms.common.utils.AbstractFuture; import me.lucko.luckperms.common.storage.Storage;
import java.util.Set; import java.util.Set;
import java.util.UUID; import java.util.UUID;
import java.util.concurrent.CompletableFuture;
import static me.lucko.luckperms.common.api.internal.Utils.*; import static me.lucko.luckperms.common.api.internal.Utils.*;
/** /**
* Provides a link between {@link Datastore} and {@link me.lucko.luckperms.common.storage.Datastore} * Provides a link between {@link Datastore} and {@link Storage}
*
* Note that this class only provides for the old deprecated interface, see {@link StorageLink} for the new one.
*/ */
@SuppressWarnings({"unused", "WeakerAccess"}) @SuppressWarnings({"unused", "WeakerAccess", "deprecation"})
public class DatastoreLink implements Datastore { public class DatastoreLink implements Datastore {
private final LuckPermsPlugin plugin; private final LuckPermsPlugin plugin;
private final me.lucko.luckperms.common.storage.Datastore master; private final Storage master;
private final Async async; private final Async async;
private final Sync sync; private final Sync sync;
private final Future future; private final Future future;
public DatastoreLink(@NonNull LuckPermsPlugin plugin, @NonNull me.lucko.luckperms.common.storage.Datastore master) { public DatastoreLink(@NonNull LuckPermsPlugin plugin, @NonNull Storage master) {
this.plugin = plugin; this.plugin = plugin;
this.master = master; this.master = master;
this.async = new Async(master); this.async = new Async(master);
@ -54,12 +57,10 @@ public class DatastoreLink implements Datastore {
this.future = new Future(master); this.future = new Future(master);
} }
private static <T> Callback<T> checkCallback(Callback<T> c) { private <T> void registerCallback(CompletableFuture<T> fut, Callback<T> c) {
// If no callback was given, just send an empty one if (c != null) {
if (c == null) { fut.thenAcceptAsync(Callback.convertToConsumer(c), plugin.getSyncExecutor());
c = Callback.empty();
} }
return c;
} }
@Override @Override
@ -89,68 +90,68 @@ public class DatastoreLink implements Datastore {
@AllArgsConstructor @AllArgsConstructor
public class Async implements Datastore.Async { public class Async implements Datastore.Async {
private final me.lucko.luckperms.common.storage.Datastore master; private final me.lucko.luckperms.common.storage.Storage master;
@Override @Override
public void logAction(@NonNull LogEntry entry, Callback<Boolean> callback) { public void logAction(@NonNull LogEntry entry, Callback<Boolean> callback) {
master.force().logAction(entry, checkCallback(callback)); registerCallback(master.force().logAction(entry), callback);
} }
@Override @Override
public void getLog(Callback<Log> callback) { public void getLog(@NonNull Callback<Log> callback) {
master.force().getLog(log -> callback.onComplete(new LogLink(log))); master.force().getLog().thenAcceptAsync(log -> callback.onComplete(new LogLink(log)), plugin.getSyncExecutor());
} }
@Override @Override
public void loadOrCreateUser(@NonNull UUID uuid, @NonNull String username, Callback<Boolean> callback) { public void loadOrCreateUser(@NonNull UUID uuid, @NonNull String username, Callback<Boolean> callback) {
master.force().loadUser(uuid, checkUsername(username), checkCallback(callback)); registerCallback(master.force().loadUser(uuid, checkUsername(username)) , callback);
} }
@Override @Override
public void loadUser(@NonNull UUID uuid, Callback<Boolean> callback) { public void loadUser(@NonNull UUID uuid, Callback<Boolean> callback) {
master.force().loadUser(uuid, "null", checkCallback(callback)); registerCallback(master.force().loadUser(uuid, "null"), callback);
} }
@Override @Override
public void loadUser(@NonNull UUID uuid, @NonNull String username, Callback<Boolean> callback) { public void loadUser(@NonNull UUID uuid, @NonNull String username, Callback<Boolean> callback) {
master.force().loadUser(uuid, checkUsername(username), checkCallback(callback)); registerCallback(master.force().loadUser(uuid, checkUsername(username)), callback);
} }
@Override @Override
public void saveUser(@NonNull User user, Callback<Boolean> callback) { public void saveUser(@NonNull User user, Callback<Boolean> callback) {
checkUser(user); checkUser(user);
master.force().saveUser(((UserLink) user).getMaster(), checkCallback(callback)); registerCallback(master.force().saveUser(((UserLink) user).getMaster()), callback);
} }
@Override @Override
public void cleanupUsers(Callback<Boolean> callback) { public void cleanupUsers(Callback<Boolean> callback) {
master.force().cleanupUsers(checkCallback(callback)); registerCallback(master.force().cleanupUsers(), callback);
} }
@Override @Override
public void getUniqueUsers(Callback<Set<UUID>> callback) { public void getUniqueUsers(Callback<Set<UUID>> callback) {
master.force().getUniqueUsers(checkCallback(callback)); registerCallback(master.force().getUniqueUsers(), callback);
} }
@Override @Override
public void createAndLoadGroup(@NonNull String name, Callback<Boolean> callback) { public void createAndLoadGroup(@NonNull String name, Callback<Boolean> callback) {
master.force().createAndLoadGroup(checkName(name), checkCallback(callback)); registerCallback(master.force().createAndLoadGroup(checkName(name)), callback);
} }
@Override @Override
public void loadGroup(@NonNull String name, Callback<Boolean> callback) { public void loadGroup(@NonNull String name, Callback<Boolean> callback) {
master.force().loadGroup(checkName(name), checkCallback(callback)); registerCallback(master.force().loadGroup(checkName(name)), callback);
} }
@Override @Override
public void loadAllGroups(Callback<Boolean> callback) { public void loadAllGroups(Callback<Boolean> callback) {
master.force().loadAllGroups(checkCallback(callback)); registerCallback(master.force().loadAllGroups(), callback);
} }
@Override @Override
public void saveGroup(@NonNull Group group, Callback<Boolean> callback) { public void saveGroup(@NonNull Group group, Callback<Boolean> callback) {
checkGroup(group); checkGroup(group);
master.force().saveGroup(((GroupLink) group).getMaster(), checkCallback(callback)); registerCallback(master.force().saveGroup(((GroupLink) group).getMaster()), callback);
} }
@Override @Override
@ -159,59 +160,59 @@ public class DatastoreLink implements Datastore {
if (group.getName().equalsIgnoreCase(plugin.getConfiguration().getDefaultGroupName())) { if (group.getName().equalsIgnoreCase(plugin.getConfiguration().getDefaultGroupName())) {
throw new IllegalArgumentException("Cannot delete the default group."); throw new IllegalArgumentException("Cannot delete the default group.");
} }
master.force().deleteGroup(((GroupLink) group).getMaster(), checkCallback(callback)); registerCallback(master.force().deleteGroup(((GroupLink) group).getMaster()), callback);
} }
@Override @Override
public void createAndLoadTrack(@NonNull String name, Callback<Boolean> callback) { public void createAndLoadTrack(@NonNull String name, Callback<Boolean> callback) {
master.force().createAndLoadTrack(checkName(name), checkCallback(callback)); registerCallback(master.force().createAndLoadTrack(checkName(name)), callback);
} }
@Override @Override
public void loadTrack(@NonNull String name, Callback<Boolean> callback) { public void loadTrack(@NonNull String name, Callback<Boolean> callback) {
master.force().loadTrack(checkName(name), checkCallback(callback)); registerCallback(master.force().loadTrack(checkName(name)), callback);
} }
@Override @Override
public void loadAllTracks(Callback<Boolean> callback) { public void loadAllTracks(Callback<Boolean> callback) {
master.force().loadAllTracks(checkCallback(callback)); registerCallback(master.force().loadAllTracks(), callback);
} }
@Override @Override
public void saveTrack(@NonNull Track track, Callback<Boolean> callback) { public void saveTrack(@NonNull Track track, Callback<Boolean> callback) {
checkTrack(track); checkTrack(track);
master.force().saveTrack(((TrackLink) track).getMaster(), checkCallback(callback)); registerCallback(master.force().saveTrack(((TrackLink) track).getMaster()), callback);
} }
@Override @Override
public void deleteTrack(@NonNull Track track, Callback<Boolean> callback) { public void deleteTrack(@NonNull Track track, Callback<Boolean> callback) {
checkTrack(track); checkTrack(track);
master.force().deleteTrack(((TrackLink) track).getMaster(), checkCallback(callback)); registerCallback(master.force().deleteTrack(((TrackLink) track).getMaster()), callback);
} }
@Override @Override
public void saveUUIDData(@NonNull String username, @NonNull UUID uuid, Callback<Boolean> callback) { public void saveUUIDData(@NonNull String username, @NonNull UUID uuid, Callback<Boolean> callback) {
master.force().saveUUIDData(checkUsername(username), uuid, checkCallback(callback)); registerCallback(master.force().saveUUIDData(checkUsername(username), uuid), callback);
} }
@Override @Override
public void getUUID(@NonNull String username, Callback<UUID> callback) { public void getUUID(@NonNull String username, Callback<UUID> callback) {
master.force().getUUID(checkUsername(username), checkCallback(callback)); registerCallback(master.force().getUUID(checkUsername(username)), callback);
} }
} }
@AllArgsConstructor @AllArgsConstructor
public class Sync implements Datastore.Sync { public class Sync implements Datastore.Sync {
private final me.lucko.luckperms.common.storage.Datastore master; private final Storage master;
@Override @Override
public boolean logAction(@NonNull LogEntry entry) { public boolean logAction(@NonNull LogEntry entry) {
return master.force().logAction(entry).getUnchecked(); return master.force().logAction(entry).join();
} }
@Override @Override
public Log getLog() { public Log getLog() {
me.lucko.luckperms.common.data.Log log = master.force().getLog().getUnchecked(); me.lucko.luckperms.common.data.Log log = master.force().getLog().join();
if (log == null) { if (log == null) {
return null; return null;
} }
@ -220,54 +221,54 @@ public class DatastoreLink implements Datastore {
@Override @Override
public boolean loadOrCreateUser(@NonNull UUID uuid, @NonNull String username) { public boolean loadOrCreateUser(@NonNull UUID uuid, @NonNull String username) {
return master.force().loadUser(uuid, checkUsername(username)).getUnchecked(); return master.force().loadUser(uuid, checkUsername(username)).join();
} }
@Override @Override
public boolean loadUser(@NonNull UUID uuid) { public boolean loadUser(@NonNull UUID uuid) {
return master.force().loadUser(uuid, "null").getUnchecked(); return master.force().loadUser(uuid, "null").join();
} }
@Override @Override
public boolean loadUser(@NonNull UUID uuid, @NonNull String username) { public boolean loadUser(@NonNull UUID uuid, @NonNull String username) {
return master.force().loadUser(uuid, checkUsername(username)).getUnchecked(); return master.force().loadUser(uuid, checkUsername(username)).join();
} }
@Override @Override
public boolean saveUser(@NonNull User user) { public boolean saveUser(@NonNull User user) {
checkUser(user); checkUser(user);
return master.force().saveUser(((UserLink) user).getMaster()).getUnchecked(); return master.force().saveUser(((UserLink) user).getMaster()).join();
} }
@Override @Override
public boolean cleanupUsers() { public boolean cleanupUsers() {
return master.force().cleanupUsers().getUnchecked(); return master.force().cleanupUsers().join();
} }
@Override @Override
public Set<UUID> getUniqueUsers() { public Set<UUID> getUniqueUsers() {
return master.force().getUniqueUsers().getUnchecked(); return master.force().getUniqueUsers().join();
} }
@Override @Override
public boolean createAndLoadGroup(@NonNull String name) { public boolean createAndLoadGroup(@NonNull String name) {
return master.force().createAndLoadGroup(checkName(name)).getUnchecked(); return master.force().createAndLoadGroup(checkName(name)).join();
} }
@Override @Override
public boolean loadGroup(@NonNull String name) { public boolean loadGroup(@NonNull String name) {
return master.force().loadGroup(checkName(name)).getUnchecked(); return master.force().loadGroup(checkName(name)).join();
} }
@Override @Override
public boolean loadAllGroups() { public boolean loadAllGroups() {
return master.force().loadAllGroups().getUnchecked(); return master.force().loadAllGroups().join();
} }
@Override @Override
public boolean saveGroup(@NonNull Group group) { public boolean saveGroup(@NonNull Group group) {
checkGroup(group); checkGroup(group);
return master.force().saveGroup(((GroupLink) group).getMaster()).getUnchecked(); return master.force().saveGroup(((GroupLink) group).getMaster()).join();
} }
@Override @Override
@ -276,50 +277,50 @@ public class DatastoreLink implements Datastore {
if (group.getName().equalsIgnoreCase(plugin.getConfiguration().getDefaultGroupName())) { if (group.getName().equalsIgnoreCase(plugin.getConfiguration().getDefaultGroupName())) {
throw new IllegalArgumentException("Cannot delete the default group."); throw new IllegalArgumentException("Cannot delete the default group.");
} }
return master.force().deleteGroup(((GroupLink) group).getMaster()).getUnchecked(); return master.force().deleteGroup(((GroupLink) group).getMaster()).join();
} }
@Override @Override
public boolean createAndLoadTrack(@NonNull String name) { public boolean createAndLoadTrack(@NonNull String name) {
return master.force().createAndLoadTrack(checkName(name)).getUnchecked(); return master.force().createAndLoadTrack(checkName(name)).join();
} }
@Override @Override
public boolean loadTrack(@NonNull String name) { public boolean loadTrack(@NonNull String name) {
return master.force().loadTrack(checkName(name)).getUnchecked(); return master.force().loadTrack(checkName(name)).join();
} }
@Override @Override
public boolean loadAllTracks() { public boolean loadAllTracks() {
return master.force().loadAllTracks().getUnchecked(); return master.force().loadAllTracks().join();
} }
@Override @Override
public boolean saveTrack(@NonNull Track track) { public boolean saveTrack(@NonNull Track track) {
checkTrack(track); checkTrack(track);
return master.force().saveTrack(((TrackLink) track).getMaster()).getUnchecked(); return master.force().saveTrack(((TrackLink) track).getMaster()).join();
} }
@Override @Override
public boolean deleteTrack(@NonNull Track track) { public boolean deleteTrack(@NonNull Track track) {
checkTrack(track); checkTrack(track);
return master.force().deleteTrack(((TrackLink) track).getMaster()).getUnchecked(); return master.force().deleteTrack(((TrackLink) track).getMaster()).join();
} }
@Override @Override
public boolean saveUUIDData(@NonNull String username, @NonNull UUID uuid) { public boolean saveUUIDData(@NonNull String username, @NonNull UUID uuid) {
return master.force().saveUUIDData(checkUsername(username), uuid).getUnchecked(); return master.force().saveUUIDData(checkUsername(username), uuid).join();
} }
@Override @Override
public UUID getUUID(@NonNull String username) { public UUID getUUID(@NonNull String username) {
return master.force().getUUID(checkUsername(username)).getUnchecked(); return master.force().getUUID(checkUsername(username)).join();
} }
} }
@AllArgsConstructor @AllArgsConstructor
public class Future implements Datastore.Future { public class Future implements Datastore.Future {
private final me.lucko.luckperms.common.storage.Datastore master; private final Storage master;
@Override @Override
public java.util.concurrent.Future<Boolean> logAction(@NonNull LogEntry entry) { public java.util.concurrent.Future<Boolean> logAction(@NonNull LogEntry entry) {
@ -328,9 +329,7 @@ public class DatastoreLink implements Datastore {
@Override @Override
public java.util.concurrent.Future<Log> getLog() { public java.util.concurrent.Future<Log> getLog() {
AbstractFuture<Log> fut = new AbstractFuture<>(); return master.force().getLog().thenApply(log -> log == null ? null : new LogLink(log));
master.force().getLog(log -> fut.complete(new LogLink(log)));
return fut;
} }
@Override @Override

View File

@ -103,7 +103,7 @@ public class LPConfigurationLink implements LPConfiguration {
@Override @Override
public boolean getDebugPermissionChecks() { public boolean getDebugPermissionChecks() {
return false; // Constant TODO depreciate this return false;
} }
@Override @Override

View File

@ -0,0 +1,162 @@
/*
* 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.api.internal;
import lombok.AllArgsConstructor;
import lombok.NonNull;
import me.lucko.luckperms.api.*;
import me.lucko.luckperms.common.LuckPermsPlugin;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Executor;
import static me.lucko.luckperms.common.api.internal.Utils.*;
/**
* Provides a link between {@link Storage} and {@link me.lucko.luckperms.common.storage.Storage}
*/
@AllArgsConstructor
public class StorageLink implements Storage {
private final LuckPermsPlugin plugin;
private final me.lucko.luckperms.common.storage.Storage master;
@Override
public String getName() {
return master.getName();
}
@Override
public boolean isAcceptingLogins() {
return master.isAcceptingLogins();
}
@Override
public Executor getSyncExecutor() {
return plugin.getSyncExecutor();
}
@Override
public Executor getAsyncExecutor() {
return plugin.getAsyncExecutor();
}
@Override
public CompletableFuture<Boolean> logAction(@NonNull LogEntry entry) {
return master.force().logAction(entry);
}
@Override
public CompletableFuture<Log> getLog() {
return master.force().getLog().thenApply(log -> log == null ? null : new LogLink(log));
}
@Override
public CompletableFuture<Boolean> loadUser(UUID uuid, String username) {
return master.force().loadUser(uuid, checkUsername(username));
}
@Override
public CompletableFuture<Boolean> saveUser(User user) {
checkUser(user);
return master.force().saveUser(((UserLink) user).getMaster());
}
@Override
public CompletableFuture<Boolean> cleanupUsers() {
return master.force().cleanupUsers();
}
@Override
public CompletableFuture<Set<UUID>> getUniqueUsers() {
return master.force().getUniqueUsers();
}
@Override
public CompletableFuture<Boolean> createAndLoadGroup(String name) {
return master.force().createAndLoadGroup(checkName(name));
}
@Override
public CompletableFuture<Boolean> loadGroup(String name) {
return master.force().loadGroup(checkName(name));
}
@Override
public CompletableFuture<Boolean> loadAllGroups() {
return master.force().loadAllGroups();
}
@Override
public CompletableFuture<Boolean> saveGroup(Group group) {
checkGroup(group);
return master.force().saveGroup(((GroupLink) group).getMaster());
}
@Override
public CompletableFuture<Boolean> deleteGroup(Group group) {
checkGroup(group);
if (group.getName().equalsIgnoreCase(plugin.getConfiguration().getDefaultGroupName())) {
throw new IllegalArgumentException("Cannot delete the default group.");
}
return master.force().deleteGroup(((GroupLink) group).getMaster());
}
@Override
public CompletableFuture<Boolean> createAndLoadTrack(String name) {
return master.force().createAndLoadTrack(checkName(name));
}
@Override
public CompletableFuture<Boolean> loadTrack(String name) {
return master.force().loadTrack(checkName(name));
}
@Override
public CompletableFuture<Boolean> loadAllTracks() {
return master.force().loadAllTracks();
}
@Override
public CompletableFuture<Boolean> saveTrack(Track track) {
checkTrack(track);
return master.force().saveTrack(((TrackLink) track).getMaster());
}
@Override
public CompletableFuture<Boolean> deleteTrack(Track track) {
checkTrack(track);
return master.force().deleteTrack(((TrackLink) track).getMaster());
}
@Override
public CompletableFuture<Boolean> saveUUIDData(String username, UUID uuid) {
return master.force().saveUUIDData(checkUsername(username), uuid);
}
@Override
public CompletableFuture<UUID> getUUID(String username) {
return master.force().getUUID(checkUsername(username));
}
}

View File

@ -114,7 +114,7 @@ public abstract class SubCommand<T> extends Command<T, Void> {
} }
public static void save(User user, Sender sender, LuckPermsPlugin plugin) { public static void save(User user, Sender sender, LuckPermsPlugin plugin) {
boolean success = plugin.getDatastore().force().saveUser(user).getUnchecked(); boolean success = plugin.getStorage().force().saveUser(user).join();
user.getRefreshBuffer().requestDirectly(); user.getRefreshBuffer().requestDirectly();
if (success) { if (success) {
@ -125,7 +125,7 @@ public abstract class SubCommand<T> extends Command<T, Void> {
} }
public static void save(Group group, Sender sender, LuckPermsPlugin plugin) { public static void save(Group group, Sender sender, LuckPermsPlugin plugin) {
boolean success = plugin.getDatastore().force().saveGroup(group).getUnchecked(); boolean success = plugin.getStorage().force().saveGroup(group).join();
plugin.getUpdateTaskBuffer().requestDirectly(); plugin.getUpdateTaskBuffer().requestDirectly();
if (success) { if (success) {
@ -136,7 +136,7 @@ public abstract class SubCommand<T> extends Command<T, Void> {
} }
public static void save(Track track, Sender sender, LuckPermsPlugin plugin) { public static void save(Track track, Sender sender, LuckPermsPlugin plugin) {
boolean success = plugin.getDatastore().force().saveTrack(track).getUnchecked(); boolean success = plugin.getStorage().force().saveTrack(track).join();
plugin.getUpdateTaskBuffer().requestDirectly(); plugin.getUpdateTaskBuffer().requestDirectly();
if (success) { if (success) {

View File

@ -46,7 +46,7 @@ public class HolderShowTracks<T extends PermissionHolder> extends SubCommand<T>
@Override @Override
public CommandResult execute(LuckPermsPlugin plugin, Sender sender, T holder, List<String> args, String label) throws CommandException { public CommandResult execute(LuckPermsPlugin plugin, Sender sender, T holder, List<String> args, String label) throws CommandException {
if (!plugin.getDatastore().loadAllTracks().getUnchecked()) { if (!plugin.getStorage().loadAllTracks().join()) {
Message.TRACKS_LOAD_ERROR.send(sender); Message.TRACKS_LOAD_ERROR.send(sender);
return CommandResult.LOADING_ERROR; return CommandResult.LOADING_ERROR;
} }

View File

@ -61,7 +61,7 @@ public class ParentAdd extends SharedSubCommand {
String server = ArgumentUtils.handleServer(1, args); String server = ArgumentUtils.handleServer(1, args);
String world = ArgumentUtils.handleWorld(2, args); String world = ArgumentUtils.handleWorld(2, args);
if (!plugin.getDatastore().loadGroup(groupName).getUnchecked()) { if (!plugin.getStorage().loadGroup(groupName).join()) {
Message.GROUP_DOES_NOT_EXIST.send(sender); Message.GROUP_DOES_NOT_EXIST.send(sender);
return CommandResult.INVALID_ARGS; return CommandResult.INVALID_ARGS;
} }

View File

@ -64,7 +64,7 @@ public class ParentAddTemp extends SharedSubCommand {
String server = ArgumentUtils.handleServer(2, args); String server = ArgumentUtils.handleServer(2, args);
String world = ArgumentUtils.handleWorld(3, args); String world = ArgumentUtils.handleWorld(3, args);
if (!plugin.getDatastore().loadGroup(groupName).getUnchecked()) { if (!plugin.getStorage().loadGroup(groupName).join()) {
Message.GROUP_DOES_NOT_EXIST.send(sender); Message.GROUP_DOES_NOT_EXIST.send(sender);
return CommandResult.INVALID_ARGS; return CommandResult.INVALID_ARGS;
} }

View File

@ -62,7 +62,7 @@ public class ParentSet extends SharedSubCommand {
String server = ArgumentUtils.handleServer(1, args); String server = ArgumentUtils.handleServer(1, args);
String world = ArgumentUtils.handleWorld(2, args); String world = ArgumentUtils.handleWorld(2, args);
if (!plugin.getDatastore().loadGroup(groupName).getUnchecked()) { if (!plugin.getStorage().loadGroup(groupName).join()) {
Message.GROUP_DOES_NOT_EXIST.send(sender); Message.GROUP_DOES_NOT_EXIST.send(sender);
return CommandResult.INVALID_ARGS; return CommandResult.INVALID_ARGS;
} }

View File

@ -57,12 +57,12 @@ public class CreateGroup extends SingleCommand {
return CommandResult.INVALID_ARGS; return CommandResult.INVALID_ARGS;
} }
if (plugin.getDatastore().loadGroup(groupName).getUnchecked()) { if (plugin.getStorage().loadGroup(groupName).join()) {
Message.GROUP_ALREADY_EXISTS.send(sender); Message.GROUP_ALREADY_EXISTS.send(sender);
return CommandResult.INVALID_ARGS; return CommandResult.INVALID_ARGS;
} }
if (!plugin.getDatastore().createAndLoadGroup(groupName).getUnchecked()) { if (!plugin.getStorage().createAndLoadGroup(groupName).join()) {
Message.CREATE_GROUP_ERROR.send(sender); Message.CREATE_GROUP_ERROR.send(sender);
return CommandResult.FAILURE; return CommandResult.FAILURE;
} }

View File

@ -61,7 +61,7 @@ public class DeleteGroup extends SingleCommand {
return CommandResult.INVALID_ARGS; return CommandResult.INVALID_ARGS;
} }
if (!plugin.getDatastore().loadGroup(groupName).getUnchecked()) { if (!plugin.getStorage().loadGroup(groupName).join()) {
Message.GROUP_DOES_NOT_EXIST.send(sender); Message.GROUP_DOES_NOT_EXIST.send(sender);
return CommandResult.INVALID_ARGS; return CommandResult.INVALID_ARGS;
} }
@ -72,7 +72,7 @@ public class DeleteGroup extends SingleCommand {
return CommandResult.LOADING_ERROR; return CommandResult.LOADING_ERROR;
} }
if (!plugin.getDatastore().deleteGroup(group).getUnchecked()) { if (!plugin.getStorage().deleteGroup(group).join()) {
Message.DELETE_GROUP_ERROR.send(sender); Message.DELETE_GROUP_ERROR.send(sender);
return CommandResult.FAILURE; return CommandResult.FAILURE;
} }

View File

@ -52,12 +52,12 @@ public class GroupClone extends SubCommand<Group> {
return CommandResult.INVALID_ARGS; return CommandResult.INVALID_ARGS;
} }
if (plugin.getDatastore().loadGroup(newGroupName).getUnchecked()) { if (plugin.getStorage().loadGroup(newGroupName).join()) {
Message.GROUP_ALREADY_EXISTS.send(sender); Message.GROUP_ALREADY_EXISTS.send(sender);
return CommandResult.INVALID_ARGS; return CommandResult.INVALID_ARGS;
} }
if (!plugin.getDatastore().createAndLoadGroup(newGroupName).getUnchecked()) { if (!plugin.getStorage().createAndLoadGroup(newGroupName).join()) {
Message.CREATE_GROUP_ERROR.send(sender); Message.CREATE_GROUP_ERROR.send(sender);
return CommandResult.FAILURE; return CommandResult.FAILURE;
} }

View File

@ -55,7 +55,7 @@ public class GroupMainCommand extends MainCommand<Group> {
@Override @Override
protected Group getTarget(String target, LuckPermsPlugin plugin, Sender sender) { protected Group getTarget(String target, LuckPermsPlugin plugin, Sender sender) {
if (!plugin.getDatastore().loadGroup(target).getUnchecked()) { if (!plugin.getStorage().loadGroup(target).join()) {
Message.GROUP_NOT_FOUND.send(sender); Message.GROUP_NOT_FOUND.send(sender);
return null; return null;
} }

View File

@ -52,12 +52,12 @@ public class GroupRename extends SubCommand<Group> {
return CommandResult.INVALID_ARGS; return CommandResult.INVALID_ARGS;
} }
if (plugin.getDatastore().loadGroup(newGroupName).getUnchecked()) { if (plugin.getStorage().loadGroup(newGroupName).join()) {
Message.GROUP_ALREADY_EXISTS.send(sender); Message.GROUP_ALREADY_EXISTS.send(sender);
return CommandResult.INVALID_ARGS; return CommandResult.INVALID_ARGS;
} }
if (!plugin.getDatastore().createAndLoadGroup(newGroupName).getUnchecked()) { if (!plugin.getStorage().createAndLoadGroup(newGroupName).join()) {
Message.CREATE_GROUP_ERROR.send(sender); Message.CREATE_GROUP_ERROR.send(sender);
return CommandResult.FAILURE; return CommandResult.FAILURE;
} }
@ -68,7 +68,7 @@ public class GroupRename extends SubCommand<Group> {
return CommandResult.LOADING_ERROR; return CommandResult.LOADING_ERROR;
} }
if (!plugin.getDatastore().deleteGroup(group).getUnchecked()) { if (!plugin.getStorage().deleteGroup(group).join()) {
Message.DELETE_GROUP_ERROR.send(sender); Message.DELETE_GROUP_ERROR.send(sender);
return CommandResult.FAILURE; return CommandResult.FAILURE;
} }

View File

@ -43,7 +43,7 @@ public class ListGroups extends SingleCommand {
@Override @Override
public CommandResult execute(LuckPermsPlugin plugin, Sender sender, List<String> args, String label) { public CommandResult execute(LuckPermsPlugin plugin, Sender sender, List<String> args, String label) {
if (!plugin.getDatastore().loadAllGroups().getUnchecked()) { if (!plugin.getStorage().loadAllGroups().join()) {
Message.GROUPS_LOAD_ERROR.send(sender); Message.GROUPS_LOAD_ERROR.send(sender);
return CommandResult.LOADING_ERROR; return CommandResult.LOADING_ERROR;
} }

View File

@ -52,7 +52,7 @@ public class LogMainCommand extends MainCommand<Log> {
@Override @Override
protected Log getTarget(String target, LuckPermsPlugin plugin, Sender sender) { protected Log getTarget(String target, LuckPermsPlugin plugin, Sender sender) {
Log log = plugin.getDatastore().getLog().getUnchecked(); Log log = plugin.getStorage().getLog().join();
if (log == null) { if (log == null) {
Message.LOG_LOAD_ERROR.send(sender); Message.LOG_LOAD_ERROR.send(sender);

View File

@ -80,7 +80,7 @@ public class LogRecent extends SubCommand<Log> {
return CommandResult.INVALID_ARGS; return CommandResult.INVALID_ARGS;
} }
UUID uuid = plugin.getDatastore().getUUID(s).getUnchecked(); UUID uuid = plugin.getStorage().getUUID(s).join();
if (uuid == null) { if (uuid == null) {
Message.USER_NOT_FOUND.send(sender); Message.USER_NOT_FOUND.send(sender);

View File

@ -82,7 +82,7 @@ public class LogUserHistory extends SubCommand<Log> {
return CommandResult.INVALID_ARGS; return CommandResult.INVALID_ARGS;
} }
UUID uuid1 = plugin.getDatastore().getUUID(user).getUnchecked(); UUID uuid1 = plugin.getStorage().getUUID(user).join();
if (uuid1 == null) { if (uuid1 == null) {
Message.USER_NOT_FOUND.send(sender); Message.USER_NOT_FOUND.send(sender);

View File

@ -33,7 +33,7 @@ import me.lucko.luckperms.common.constants.Constants;
import me.lucko.luckperms.common.constants.Message; import me.lucko.luckperms.common.constants.Message;
import me.lucko.luckperms.common.constants.Permission; import me.lucko.luckperms.common.constants.Permission;
import me.lucko.luckperms.common.groups.Group; import me.lucko.luckperms.common.groups.Group;
import me.lucko.luckperms.common.storage.Datastore; import me.lucko.luckperms.common.storage.Storage;
import me.lucko.luckperms.common.tracks.Track; import me.lucko.luckperms.common.tracks.Track;
import me.lucko.luckperms.common.users.User; import me.lucko.luckperms.common.users.User;
import me.lucko.luckperms.common.utils.Predicates; import me.lucko.luckperms.common.utils.Predicates;
@ -123,14 +123,14 @@ public class ExportCommand extends SingleCommand {
// Export users // Export users
log.info("Export: Exporting all users. Finding a list of unique users to export."); log.info("Export: Exporting all users. Finding a list of unique users to export.");
Datastore ds = plugin.getDatastore(); Storage ds = plugin.getStorage();
Set<UUID> users = ds.getUniqueUsers().getUnchecked(); Set<UUID> users = ds.getUniqueUsers().join();
log.info("Export: Found " + users.size() + " unique users to export."); log.info("Export: Found " + users.size() + " unique users to export.");
int userCount = 0; int userCount = 0;
for (UUID uuid : users) { for (UUID uuid : users) {
userCount++; userCount++;
plugin.getDatastore().loadUser(uuid, "null").getUnchecked(); plugin.getStorage().loadUser(uuid, "null").join();
User user = plugin.getUserManager().get(uuid); User user = plugin.getUserManager().get(uuid);
boolean inDefault = false; boolean inDefault = false;

View File

@ -46,7 +46,7 @@ public class InfoCommand extends SingleCommand {
Message.INFO.send(sender, Message.INFO.send(sender,
plugin.getVersion(), plugin.getVersion(),
plugin.getType().getFriendlyName(), plugin.getType().getFriendlyName(),
plugin.getDatastore().getName(), plugin.getStorage().getName(),
c.getServer(), c.getServer(),
c.getSyncTime(), c.getSyncTime(),
formatBoolean(c.isIncludingGlobalPerms()), formatBoolean(c.isIncludingGlobalPerms()),

View File

@ -41,7 +41,7 @@ public class NetworkSyncCommand extends SingleCommand {
@Override @Override
public CommandResult execute(LuckPermsPlugin plugin, Sender sender, List<String> args, String label) { public CommandResult execute(LuckPermsPlugin plugin, Sender sender, List<String> args, String label) {
Message.UPDATE_TASK_REQUEST.send(sender); Message.UPDATE_TASK_REQUEST.send(sender);
plugin.getUpdateTaskBuffer().request().getUnchecked(); plugin.getUpdateTaskBuffer().request().join();
Message.UPDATE_TASK_COMPLETE_NETWORK.send(sender); Message.UPDATE_TASK_COMPLETE_NETWORK.send(sender);
if (plugin.getRedisMessaging() != null) { if (plugin.getRedisMessaging() != null) {

View File

@ -40,7 +40,7 @@ public class SyncCommand extends SingleCommand {
@Override @Override
public CommandResult execute(LuckPermsPlugin plugin, Sender sender, List<String> args, String label) { public CommandResult execute(LuckPermsPlugin plugin, Sender sender, List<String> args, String label) {
Message.UPDATE_TASK_REQUEST.send(sender); Message.UPDATE_TASK_REQUEST.send(sender);
plugin.getUpdateTaskBuffer().request().getUnchecked(); plugin.getUpdateTaskBuffer().request().join();
Message.UPDATE_TASK_COMPLETE.send(sender); Message.UPDATE_TASK_COMPLETE.send(sender);
return CommandResult.SUCCESS; return CommandResult.SUCCESS;
} }

View File

@ -57,12 +57,12 @@ public class CreateTrack extends SingleCommand {
return CommandResult.INVALID_ARGS; return CommandResult.INVALID_ARGS;
} }
if (plugin.getDatastore().loadTrack(trackName).getUnchecked()) { if (plugin.getStorage().loadTrack(trackName).join()) {
Message.TRACK_ALREADY_EXISTS.send(sender); Message.TRACK_ALREADY_EXISTS.send(sender);
return CommandResult.INVALID_ARGS; return CommandResult.INVALID_ARGS;
} }
if (!plugin.getDatastore().createAndLoadTrack(trackName).getUnchecked()) { if (!plugin.getStorage().createAndLoadTrack(trackName).join()) {
Message.CREATE_TRACK_ERROR.send(sender); Message.CREATE_TRACK_ERROR.send(sender);
return CommandResult.FAILURE; return CommandResult.FAILURE;
} }

View File

@ -55,7 +55,7 @@ public class DeleteTrack extends SingleCommand {
} }
String trackName = args.get(0).toLowerCase(); String trackName = args.get(0).toLowerCase();
if (!plugin.getDatastore().loadTrack(trackName).getUnchecked()) { if (!plugin.getStorage().loadTrack(trackName).join()) {
Message.TRACK_DOES_NOT_EXIST.send(sender); Message.TRACK_DOES_NOT_EXIST.send(sender);
return CommandResult.INVALID_ARGS; return CommandResult.INVALID_ARGS;
} }
@ -66,7 +66,7 @@ public class DeleteTrack extends SingleCommand {
return CommandResult.LOADING_ERROR; return CommandResult.LOADING_ERROR;
} }
if (!plugin.getDatastore().deleteTrack(track).getUnchecked()) { if (!plugin.getStorage().deleteTrack(track).join()) {
Message.DELETE_TRACK_ERROR.send(sender); Message.DELETE_TRACK_ERROR.send(sender);
return CommandResult.FAILURE; return CommandResult.FAILURE;
} }

View File

@ -41,7 +41,7 @@ public class ListTracks extends SingleCommand {
@Override @Override
public CommandResult execute(LuckPermsPlugin plugin, Sender sender, List<String> args, String label) { public CommandResult execute(LuckPermsPlugin plugin, Sender sender, List<String> args, String label) {
if (!plugin.getDatastore().loadAllTracks().getUnchecked()) { if (!plugin.getStorage().loadAllTracks().join()) {
Message.TRACKS_LOAD_ERROR.send(sender); Message.TRACKS_LOAD_ERROR.send(sender);
return CommandResult.LOADING_ERROR; return CommandResult.LOADING_ERROR;
} }

View File

@ -56,7 +56,7 @@ public class TrackAppend extends SubCommand<Track> {
return CommandResult.INVALID_ARGS; return CommandResult.INVALID_ARGS;
} }
if (!plugin.getDatastore().loadGroup(groupName).getUnchecked()) { if (!plugin.getStorage().loadGroup(groupName).join()) {
Message.GROUP_DOES_NOT_EXIST.send(sender); Message.GROUP_DOES_NOT_EXIST.send(sender);
return CommandResult.INVALID_ARGS; return CommandResult.INVALID_ARGS;
} }

View File

@ -52,12 +52,12 @@ public class TrackClone extends SubCommand<Track> {
return CommandResult.INVALID_ARGS; return CommandResult.INVALID_ARGS;
} }
if (plugin.getDatastore().loadTrack(newTrackName).getUnchecked()) { if (plugin.getStorage().loadTrack(newTrackName).join()) {
Message.TRACK_ALREADY_EXISTS.send(sender); Message.TRACK_ALREADY_EXISTS.send(sender);
return CommandResult.INVALID_ARGS; return CommandResult.INVALID_ARGS;
} }
if (!plugin.getDatastore().createAndLoadTrack(newTrackName).getUnchecked()) { if (!plugin.getStorage().createAndLoadTrack(newTrackName).join()) {
Message.CREATE_TRACK_ERROR.send(sender); Message.CREATE_TRACK_ERROR.send(sender);
return CommandResult.FAILURE; return CommandResult.FAILURE;
} }

View File

@ -67,7 +67,7 @@ public class TrackInsert extends SubCommand<Track> {
return CommandResult.INVALID_ARGS; return CommandResult.INVALID_ARGS;
} }
if (!plugin.getDatastore().loadGroup(groupName).getUnchecked()) { if (!plugin.getStorage().loadGroup(groupName).join()) {
Message.GROUP_DOES_NOT_EXIST.send(sender); Message.GROUP_DOES_NOT_EXIST.send(sender);
return CommandResult.INVALID_ARGS; return CommandResult.INVALID_ARGS;
} }

View File

@ -49,7 +49,7 @@ public class TrackMainCommand extends MainCommand<Track> {
@Override @Override
protected Track getTarget(String target, LuckPermsPlugin plugin, Sender sender) { protected Track getTarget(String target, LuckPermsPlugin plugin, Sender sender) {
if (!plugin.getDatastore().loadTrack(target).getUnchecked()) { if (!plugin.getStorage().loadTrack(target).join()) {
Message.TRACK_NOT_FOUND.send(sender); Message.TRACK_NOT_FOUND.send(sender);
return null; return null;
} }

View File

@ -52,12 +52,12 @@ public class TrackRename extends SubCommand<Track> {
return CommandResult.INVALID_ARGS; return CommandResult.INVALID_ARGS;
} }
if (plugin.getDatastore().loadTrack(newTrackName).getUnchecked()) { if (plugin.getStorage().loadTrack(newTrackName).join()) {
Message.TRACK_ALREADY_EXISTS.send(sender); Message.TRACK_ALREADY_EXISTS.send(sender);
return CommandResult.INVALID_ARGS; return CommandResult.INVALID_ARGS;
} }
if (!plugin.getDatastore().createAndLoadTrack(newTrackName).getUnchecked()) { if (!plugin.getStorage().createAndLoadTrack(newTrackName).join()) {
Message.CREATE_TRACK_ERROR.send(sender); Message.CREATE_TRACK_ERROR.send(sender);
return CommandResult.FAILURE; return CommandResult.FAILURE;
} }
@ -68,7 +68,7 @@ public class TrackRename extends SubCommand<Track> {
return CommandResult.LOADING_ERROR; return CommandResult.LOADING_ERROR;
} }
if (!plugin.getDatastore().deleteTrack(track).getUnchecked()) { if (!plugin.getStorage().deleteTrack(track).join()) {
Message.DELETE_TRACK_ERROR.send(sender); Message.DELETE_TRACK_ERROR.send(sender);
return CommandResult.FAILURE; return CommandResult.FAILURE;
} }

View File

@ -72,7 +72,7 @@ public class UserDemote extends SubCommand<User> {
return CommandResult.INVALID_ARGS; return CommandResult.INVALID_ARGS;
} }
if (!plugin.getDatastore().loadTrack(trackName).getUnchecked()) { if (!plugin.getStorage().loadTrack(trackName).join()) {
Message.TRACK_DOES_NOT_EXIST.send(sender); Message.TRACK_DOES_NOT_EXIST.send(sender);
return CommandResult.INVALID_ARGS; return CommandResult.INVALID_ARGS;
} }
@ -147,7 +147,7 @@ public class UserDemote extends SubCommand<User> {
return CommandResult.STATE_ERROR; return CommandResult.STATE_ERROR;
} }
if (!plugin.getDatastore().loadGroup(previous).getUnchecked()) { if (!plugin.getStorage().loadGroup(previous).join()) {
Message.USER_DEMOTE_ERROR_MALFORMED.send(sender, previous); Message.USER_DEMOTE_ERROR_MALFORMED.send(sender, previous);
return CommandResult.STATE_ERROR; return CommandResult.STATE_ERROR;
} }

View File

@ -67,7 +67,7 @@ public class UserMainCommand extends MainCommand<User> {
return null; return null;
} }
u = plugin.getDatastore().getUUID(target).getUnchecked(); u = plugin.getStorage().getUUID(target).join();
if (u == null) { if (u == null) {
Message.USER_NOT_FOUND.send(sender); Message.USER_NOT_FOUND.send(sender);
return null; return null;
@ -77,10 +77,10 @@ public class UserMainCommand extends MainCommand<User> {
} }
} }
String name = plugin.getDatastore().getName(u).getUnchecked(); String name = plugin.getStorage().getName(u).join();
if (name == null) name = "null"; if (name == null) name = "null";
if (!plugin.getDatastore().loadUser(u, name).getUnchecked()) { if (!plugin.getStorage().loadUser(u, name).join()) {
Message.LOADING_ERROR.send(sender); Message.LOADING_ERROR.send(sender);
} }

View File

@ -72,7 +72,7 @@ public class UserPromote extends SubCommand<User> {
return CommandResult.INVALID_ARGS; return CommandResult.INVALID_ARGS;
} }
if (!plugin.getDatastore().loadTrack(trackName).getUnchecked()) { if (!plugin.getStorage().loadTrack(trackName).join()) {
Message.TRACK_DOES_NOT_EXIST.send(sender); Message.TRACK_DOES_NOT_EXIST.send(sender);
return CommandResult.INVALID_ARGS; return CommandResult.INVALID_ARGS;
} }
@ -147,7 +147,7 @@ public class UserPromote extends SubCommand<User> {
return CommandResult.STATE_ERROR; return CommandResult.STATE_ERROR;
} }
if (!plugin.getDatastore().loadGroup(next).getUnchecked()) { if (!plugin.getStorage().loadGroup(next).join()) {
Message.USER_PROMOTE_ERROR_MALFORMED.send(sender, next); Message.USER_PROMOTE_ERROR_MALFORMED.send(sender, next);
return CommandResult.STATE_ERROR; return CommandResult.STATE_ERROR;
} }

View File

@ -32,7 +32,7 @@ import me.lucko.luckperms.common.commands.sender.Sender;
import me.lucko.luckperms.common.constants.Message; import me.lucko.luckperms.common.constants.Message;
import me.lucko.luckperms.common.constants.Permission; import me.lucko.luckperms.common.constants.Permission;
import me.lucko.luckperms.common.core.NodeFactory; import me.lucko.luckperms.common.core.NodeFactory;
import me.lucko.luckperms.common.storage.Datastore; import me.lucko.luckperms.common.storage.Storage;
import me.lucko.luckperms.common.users.User; import me.lucko.luckperms.common.users.User;
import me.lucko.luckperms.common.utils.Predicates; import me.lucko.luckperms.common.utils.Predicates;
import me.lucko.luckperms.exceptions.ObjectAlreadyHasException; import me.lucko.luckperms.exceptions.ObjectAlreadyHasException;
@ -40,7 +40,7 @@ import me.lucko.luckperms.exceptions.ObjectLacksException;
import java.util.*; import java.util.*;
public class BulkEditGroup extends SubCommand<Datastore> { public class BulkEditGroup extends SubCommand<Storage> {
public BulkEditGroup() { public BulkEditGroup() {
super("group", "Bulk edit group memberships", Permission.USER_BULKCHANGE, Predicates.not(4), super("group", "Bulk edit group memberships", Permission.USER_BULKCHANGE, Predicates.not(4),
Arg.list( Arg.list(
@ -53,7 +53,7 @@ public class BulkEditGroup extends SubCommand<Datastore> {
} }
@Override @Override
public CommandResult execute(LuckPermsPlugin plugin, Sender sender, Datastore datastore, List<String> args, String label) throws CommandException { public CommandResult execute(LuckPermsPlugin plugin, Sender sender, Storage storage, List<String> args, String label) throws CommandException {
String group = args.get(0); String group = args.get(0);
String type = args.get(1).toLowerCase(); String type = args.get(1).toLowerCase();
String from = args.get(2); String from = args.get(2);
@ -67,10 +67,10 @@ public class BulkEditGroup extends SubCommand<Datastore> {
return CommandResult.FAILURE; return CommandResult.FAILURE;
} }
Set<UUID> uuids = datastore.getUniqueUsers().getUnchecked(); Set<UUID> uuids = storage.getUniqueUsers().join();
for (UUID u : uuids) { for (UUID u : uuids) {
plugin.getDatastore().loadUser(u, "null").getUnchecked(); plugin.getStorage().loadUser(u, "null").join();
User user = plugin.getUserManager().get(u); User user = plugin.getUserManager().get(u);
if (user == null) { if (user == null) {
continue; continue;
@ -143,7 +143,7 @@ public class BulkEditGroup extends SubCommand<Datastore> {
} catch (ObjectAlreadyHasException ignored) {} } catch (ObjectAlreadyHasException ignored) {}
}); });
plugin.getDatastore().saveUser(user); plugin.getStorage().saveUser(user);
plugin.getUserManager().cleanup(user); plugin.getUserManager().cleanup(user);
} }

View File

@ -32,7 +32,7 @@ import me.lucko.luckperms.common.commands.sender.Sender;
import me.lucko.luckperms.common.constants.Message; import me.lucko.luckperms.common.constants.Message;
import me.lucko.luckperms.common.constants.Permission; import me.lucko.luckperms.common.constants.Permission;
import me.lucko.luckperms.common.core.NodeFactory; import me.lucko.luckperms.common.core.NodeFactory;
import me.lucko.luckperms.common.storage.Datastore; import me.lucko.luckperms.common.storage.Storage;
import me.lucko.luckperms.common.users.User; import me.lucko.luckperms.common.users.User;
import me.lucko.luckperms.common.utils.Predicates; import me.lucko.luckperms.common.utils.Predicates;
import me.lucko.luckperms.exceptions.ObjectAlreadyHasException; import me.lucko.luckperms.exceptions.ObjectAlreadyHasException;
@ -40,7 +40,7 @@ import me.lucko.luckperms.exceptions.ObjectLacksException;
import java.util.*; import java.util.*;
public class BulkEditPermission extends SubCommand<Datastore> { public class BulkEditPermission extends SubCommand<Storage> {
public BulkEditPermission() { public BulkEditPermission() {
super("permission", "Bulk edit permissions", Permission.USER_BULKCHANGE, Predicates.not(4), super("permission", "Bulk edit permissions", Permission.USER_BULKCHANGE, Predicates.not(4),
Arg.list( Arg.list(
@ -53,7 +53,7 @@ public class BulkEditPermission extends SubCommand<Datastore> {
} }
@Override @Override
public CommandResult execute(LuckPermsPlugin plugin, Sender sender, Datastore datastore, List<String> args, String label) throws CommandException { public CommandResult execute(LuckPermsPlugin plugin, Sender sender, Storage storage, List<String> args, String label) throws CommandException {
String node = args.get(0); String node = args.get(0);
String type = args.get(1).toLowerCase(); String type = args.get(1).toLowerCase();
String from = args.get(2); String from = args.get(2);
@ -67,10 +67,10 @@ public class BulkEditPermission extends SubCommand<Datastore> {
return CommandResult.FAILURE; return CommandResult.FAILURE;
} }
Set<UUID> uuids = datastore.getUniqueUsers().getUnchecked(); Set<UUID> uuids = storage.getUniqueUsers().join();
for (UUID u : uuids) { for (UUID u : uuids) {
plugin.getDatastore().loadUser(u, "null").getUnchecked(); plugin.getStorage().loadUser(u, "null").join();
User user = plugin.getUserManager().get(u); User user = plugin.getUserManager().get(u);
if (user == null) { if (user == null) {
continue; continue;
@ -133,7 +133,7 @@ public class BulkEditPermission extends SubCommand<Datastore> {
} catch (ObjectAlreadyHasException ignored) {} } catch (ObjectAlreadyHasException ignored) {}
}); });
plugin.getDatastore().saveUser(user); plugin.getStorage().saveUser(user);
plugin.getUserManager().cleanup(user); plugin.getUserManager().cleanup(user);
} }

View File

@ -27,17 +27,17 @@ import me.lucko.luckperms.common.LuckPermsPlugin;
import me.lucko.luckperms.common.commands.Command; import me.lucko.luckperms.common.commands.Command;
import me.lucko.luckperms.common.commands.MainCommand; import me.lucko.luckperms.common.commands.MainCommand;
import me.lucko.luckperms.common.commands.sender.Sender; import me.lucko.luckperms.common.commands.sender.Sender;
import me.lucko.luckperms.common.storage.Datastore; import me.lucko.luckperms.common.storage.Storage;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.Optional; import java.util.Optional;
import java.util.stream.Collectors; import java.util.stream.Collectors;
public class UsersBulkEditMainCommand extends MainCommand<Datastore> { public class UsersBulkEditMainCommand extends MainCommand<Storage> {
public UsersBulkEditMainCommand() { public UsersBulkEditMainCommand() {
super("UsersBulkEdit", "User bulk edit commands", "/%s usersbulkedit", 1, ImmutableList.<Command<Datastore, ?>>builder() super("UsersBulkEdit", "User bulk edit commands", "/%s usersbulkedit", 1, ImmutableList.<Command<Storage, ?>>builder()
.add(new BulkEditGroup()) .add(new BulkEditGroup())
.add(new BulkEditPermission()) .add(new BulkEditPermission())
.build() .build()
@ -45,12 +45,12 @@ public class UsersBulkEditMainCommand extends MainCommand<Datastore> {
} }
@Override @Override
protected Datastore getTarget(String target, LuckPermsPlugin plugin, Sender sender) { protected Storage getTarget(String target, LuckPermsPlugin plugin, Sender sender) {
return plugin.getDatastore(); return plugin.getStorage();
} }
@Override @Override
protected void cleanup(Datastore datastore, LuckPermsPlugin plugin) { protected void cleanup(Storage storage, LuckPermsPlugin plugin) {
} }
@ -61,7 +61,7 @@ public class UsersBulkEditMainCommand extends MainCommand<Datastore> {
@Override @Override
public List<String> tabComplete(LuckPermsPlugin plugin, Sender sender, List<String> args) { public List<String> tabComplete(LuckPermsPlugin plugin, Sender sender, List<String> args) {
final List<Command<Datastore, ?>> subs = getSubCommands().stream() final List<Command<Storage, ?>> subs = getSubCommands().stream()
.filter(s -> s.isAuthorized(sender)) .filter(s -> s.isAuthorized(sender))
.collect(Collectors.toList()); .collect(Collectors.toList());
@ -78,7 +78,7 @@ public class UsersBulkEditMainCommand extends MainCommand<Datastore> {
.collect(Collectors.toList()); .collect(Collectors.toList());
} }
Optional<Command<Datastore, ?>> o = subs.stream() Optional<Command<Storage, ?>> o = subs.stream()
.filter(s -> s.getName().equalsIgnoreCase(args.get(0))) .filter(s -> s.getName().equalsIgnoreCase(args.get(0)))
.limit(1) .limit(1)
.findAny(); .findAny();

View File

@ -56,16 +56,16 @@ public enum Message {
* Loading / Saving * Loading / Saving
*/ */
USER_NOT_FOUND("&bUser could not be found.", true), USER_NOT_FOUND("&bUser could not be found.", true),
USER_SAVE_SUCCESS("&7(User data was saved to the datastore)", true), USER_SAVE_SUCCESS("&7(User data was saved to storage)", true),
USER_SAVE_ERROR("There was an error whilst saving the user.", true), USER_SAVE_ERROR("There was an error whilst saving the user.", true),
USER_CREATE_FAIL("There was an error whilst creating a new user.", true), USER_CREATE_FAIL("There was an error whilst creating a new user.", true),
GROUP_NOT_FOUND("&bGroup could not be found.", true), GROUP_NOT_FOUND("&bGroup could not be found.", true),
GROUP_SAVE_SUCCESS("&7(Group data was saved to the datastore)", true), GROUP_SAVE_SUCCESS("&7(Group data was saved to storage)", true),
GROUP_SAVE_ERROR("There was an error whilst saving the group.", true), GROUP_SAVE_ERROR("There was an error whilst saving the group.", true),
TRACK_NOT_FOUND("&bTrack could not be found.", true), TRACK_NOT_FOUND("&bTrack could not be found.", true),
TRACK_SAVE_SUCCESS("&7(Track data was saved to the datastore)", true), TRACK_SAVE_SUCCESS("&7(Track data was saved to storage)", true),
TRACK_SAVE_ERROR("There was an error whilst saving the track.", true), TRACK_SAVE_ERROR("There was an error whilst saving the track.", true),

View File

@ -48,7 +48,7 @@ public class LogEntry extends me.lucko.luckperms.api.LogEntry {
} }
public void submit(LuckPermsPlugin plugin, Sender sender) { public void submit(LuckPermsPlugin plugin, Sender sender) {
plugin.getDatastore().logAction(this); plugin.getStorage().logAction(this);
LogNotifyEvent event = new LogNotifyEvent(this); LogNotifyEvent event = new LogNotifyEvent(this);
event.setCancelled(!plugin.getConfiguration().isLogNotify()); event.setCancelled(!plugin.getConfiguration().isLogNotify());

View File

@ -23,6 +23,7 @@
package me.lucko.luckperms.common.messaging; package me.lucko.luckperms.common.messaging;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import me.lucko.luckperms.api.MessagingService;
import me.lucko.luckperms.common.LuckPermsPlugin; import me.lucko.luckperms.common.LuckPermsPlugin;
import redis.clients.jedis.Jedis; import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool; import redis.clients.jedis.JedisPool;
@ -38,7 +39,7 @@ import java.util.UUID;
* Uses Redis to push/receive changes to/from other servers * Uses Redis to push/receive changes to/from other servers
*/ */
@RequiredArgsConstructor @RequiredArgsConstructor
public class RedisMessaging { public class RedisMessaging implements MessagingService {
private static final String CHANNEL = "luckperms"; private static final String CHANNEL = "luckperms";
private final LuckPermsPlugin plugin; private final LuckPermsPlugin plugin;
@ -70,6 +71,7 @@ public class RedisMessaging {
jedisPool.destroy(); jedisPool.destroy();
} }
@Override
public void pushUpdate() { public void pushUpdate() {
plugin.doAsync(() -> { plugin.doAsync(() -> {
UUID id = sub.generateId(); UUID id = sub.generateId();

View File

@ -36,14 +36,14 @@ public class ExpireTemporaryTask implements Runnable {
boolean groupChanges = false; boolean groupChanges = false;
for (Group group : plugin.getGroupManager().getAll().values()) { for (Group group : plugin.getGroupManager().getAll().values()) {
if (group.auditTemporaryPermissions()) { if (group.auditTemporaryPermissions()) {
plugin.getDatastore().saveGroup(group); plugin.getStorage().saveGroup(group);
groupChanges = true; groupChanges = true;
} }
} }
for (User user : plugin.getUserManager().getAll().values()) { for (User user : plugin.getUserManager().getAll().values()) {
if (user.auditTemporaryPermissions()) { if (user.auditTemporaryPermissions()) {
plugin.getDatastore().saveUser(user); plugin.getStorage().saveUser(user);
if (!groupChanges) { if (!groupChanges) {
user.getRefreshBuffer().request(); user.getRefreshBuffer().request();
} }

View File

@ -41,14 +41,14 @@ public class UpdateTask implements Runnable {
if (event.isCancelled()) return; if (event.isCancelled()) return;
// Reload all groups // Reload all groups
plugin.getDatastore().loadAllGroups().getUnchecked(); plugin.getStorage().loadAllGroups().join();
String defaultGroup = plugin.getConfiguration().getDefaultGroupName(); String defaultGroup = plugin.getConfiguration().getDefaultGroupName();
if (!plugin.getGroupManager().isLoaded(defaultGroup)) { if (!plugin.getGroupManager().isLoaded(defaultGroup)) {
plugin.getDatastore().createAndLoadGroup(defaultGroup).getUnchecked(); plugin.getStorage().createAndLoadGroup(defaultGroup).join();
} }
// Reload all tracks // Reload all tracks
plugin.getDatastore().loadAllTracks().getUnchecked(); plugin.getStorage().loadAllTracks().join();
// Refresh all online users. // Refresh all online users.
plugin.getUserManager().updateAllUsers(); plugin.getUserManager().updateAllUsers();

View File

@ -32,21 +32,19 @@ import me.lucko.luckperms.common.groups.Group;
import me.lucko.luckperms.common.storage.backing.AbstractBacking; import me.lucko.luckperms.common.storage.backing.AbstractBacking;
import me.lucko.luckperms.common.tracks.Track; import me.lucko.luckperms.common.tracks.Track;
import me.lucko.luckperms.common.users.User; import me.lucko.luckperms.common.users.User;
import me.lucko.luckperms.common.utils.AbstractFuture;
import me.lucko.luckperms.common.utils.LPFuture;
import java.util.Set; import java.util.Set;
import java.util.UUID; import java.util.UUID;
import java.util.concurrent.Future; import java.util.concurrent.CompletableFuture;
import java.util.function.Supplier; import java.util.function.Supplier;
/** /**
* Converts a {@link AbstractBacking} to use {@link Future}s * Converts a {@link AbstractBacking} to use {@link CompletableFuture}s
*/ */
@RequiredArgsConstructor(access = AccessLevel.PRIVATE) @RequiredArgsConstructor(access = AccessLevel.PRIVATE)
public class AbstractDatastore implements Datastore { public class AbstractStorage implements Storage {
public static Datastore wrap(LuckPermsPlugin plugin, AbstractBacking backing) { public static Storage wrap(LuckPermsPlugin plugin, AbstractBacking backing) {
BufferedOutputDatastore bufferedDs = BufferedOutputDatastore.wrap(TolerantDatastore.wrap(new AbstractDatastore(backing)), 1000L); BufferedOutputStorage bufferedDs = BufferedOutputStorage.wrap(TolerantStorage.wrap(new AbstractStorage(backing)), 1000L);
plugin.doAsyncRepeating(bufferedDs, 10L); plugin.doAsyncRepeating(bufferedDs, 10L);
return bufferedDs; return bufferedDs;
} }
@ -54,112 +52,107 @@ public class AbstractDatastore implements Datastore {
@Delegate(types = Delegated.class) @Delegate(types = Delegated.class)
private final AbstractBacking backing; private final AbstractBacking backing;
private <T> LPFuture<T> makeFuture(Supplier<T> supplier) { private <T> CompletableFuture<T> makeFuture(Supplier<T> supplier) {
AbstractFuture<T> future = new AbstractFuture<>(); return CompletableFuture.supplyAsync(supplier, backing.getPlugin().getAsyncExecutor());
backing.doAsync(() -> {
T result = supplier.get();
future.complete(result);
});
return future;
} }
@Override @Override
public Datastore force() { public Storage force() {
return this; return this;
} }
@Override @Override
public LPFuture<Boolean> logAction(LogEntry entry) { public CompletableFuture<Boolean> logAction(LogEntry entry) {
return makeFuture(() -> backing.logAction(entry)); return makeFuture(() -> backing.logAction(entry));
} }
@Override @Override
public LPFuture<Log> getLog() { public CompletableFuture<Log> getLog() {
return makeFuture(backing::getLog); return makeFuture(backing::getLog);
} }
@Override @Override
public LPFuture<Boolean> loadUser(UUID uuid, String username) { public CompletableFuture<Boolean> loadUser(UUID uuid, String username) {
return makeFuture(() -> backing.loadUser(uuid, username)); return makeFuture(() -> backing.loadUser(uuid, username));
} }
@Override @Override
public LPFuture<Boolean> saveUser(User user) { public CompletableFuture<Boolean> saveUser(User user) {
return makeFuture(() -> backing.saveUser(user)); return makeFuture(() -> backing.saveUser(user));
} }
@Override @Override
public LPFuture<Boolean> cleanupUsers() { public CompletableFuture<Boolean> cleanupUsers() {
return makeFuture(backing::cleanupUsers); return makeFuture(backing::cleanupUsers);
} }
@Override @Override
public LPFuture<Set<UUID>> getUniqueUsers() { public CompletableFuture<Set<UUID>> getUniqueUsers() {
return makeFuture(backing::getUniqueUsers); return makeFuture(backing::getUniqueUsers);
} }
@Override @Override
public LPFuture<Boolean> createAndLoadGroup(String name) { public CompletableFuture<Boolean> createAndLoadGroup(String name) {
return makeFuture(() -> backing.createAndLoadGroup(name)); return makeFuture(() -> backing.createAndLoadGroup(name));
} }
@Override @Override
public LPFuture<Boolean> loadGroup(String name) { public CompletableFuture<Boolean> loadGroup(String name) {
return makeFuture(() -> backing.loadGroup(name)); return makeFuture(() -> backing.loadGroup(name));
} }
@Override @Override
public LPFuture<Boolean> loadAllGroups() { public CompletableFuture<Boolean> loadAllGroups() {
return makeFuture(backing::loadAllGroups); return makeFuture(backing::loadAllGroups);
} }
@Override @Override
public LPFuture<Boolean> saveGroup(Group group) { public CompletableFuture<Boolean> saveGroup(Group group) {
return makeFuture(() -> backing.saveGroup(group)); return makeFuture(() -> backing.saveGroup(group));
} }
@Override @Override
public LPFuture<Boolean> deleteGroup(Group group) { public CompletableFuture<Boolean> deleteGroup(Group group) {
return makeFuture(() -> backing.deleteGroup(group)); return makeFuture(() -> backing.deleteGroup(group));
} }
@Override @Override
public LPFuture<Boolean> createAndLoadTrack(String name) { public CompletableFuture<Boolean> createAndLoadTrack(String name) {
return makeFuture(() -> backing.createAndLoadTrack(name)); return makeFuture(() -> backing.createAndLoadTrack(name));
} }
@Override @Override
public LPFuture<Boolean> loadTrack(String name) { public CompletableFuture<Boolean> loadTrack(String name) {
return makeFuture(() -> backing.loadTrack(name)); return makeFuture(() -> backing.loadTrack(name));
} }
@Override @Override
public LPFuture<Boolean> loadAllTracks() { public CompletableFuture<Boolean> loadAllTracks() {
return makeFuture(backing::loadAllTracks); return makeFuture(backing::loadAllTracks);
} }
@Override @Override
public LPFuture<Boolean> saveTrack(Track track) { public CompletableFuture<Boolean> saveTrack(Track track) {
return makeFuture(() -> backing.saveTrack(track)); return makeFuture(() -> backing.saveTrack(track));
} }
@Override @Override
public LPFuture<Boolean> deleteTrack(Track track) { public CompletableFuture<Boolean> deleteTrack(Track track) {
return makeFuture(() -> backing.deleteTrack(track)); return makeFuture(() -> backing.deleteTrack(track));
} }
@Override @Override
public LPFuture<Boolean> saveUUIDData(String username, UUID uuid) { public CompletableFuture<Boolean> saveUUIDData(String username, UUID uuid) {
return makeFuture(() -> backing.saveUUIDData(username, uuid)); return makeFuture(() -> backing.saveUUIDData(username, uuid));
} }
@Override @Override
public LPFuture<UUID> getUUID(String username) { public CompletableFuture<UUID> getUUID(String username) {
return makeFuture(() -> backing.getUUID(username)); return makeFuture(() -> backing.getUUID(username));
} }
@Override @Override
public LPFuture<String> getName(UUID uuid) { public CompletableFuture<String> getName(UUID uuid) {
return makeFuture(() -> backing.getName(uuid)); return makeFuture(() -> backing.getName(uuid));
} }
@ -167,8 +160,6 @@ public class AbstractDatastore implements Datastore {
String getName(); String getName();
boolean isAcceptingLogins(); boolean isAcceptingLogins();
void setAcceptingLogins(boolean b); void setAcceptingLogins(boolean b);
void doAsync(Runnable r);
void doSync(Runnable r);
void init(); void init();
void shutdown(); void shutdown();
} }

View File

@ -31,47 +31,47 @@ import me.lucko.luckperms.common.tracks.Track;
import me.lucko.luckperms.common.users.User; import me.lucko.luckperms.common.users.User;
import me.lucko.luckperms.common.users.UserIdentifier; import me.lucko.luckperms.common.users.UserIdentifier;
import me.lucko.luckperms.common.utils.Buffer; import me.lucko.luckperms.common.utils.Buffer;
import me.lucko.luckperms.common.utils.LPFuture;
import java.util.UUID; import java.util.UUID;
import java.util.concurrent.CompletableFuture;
@RequiredArgsConstructor(access = AccessLevel.PRIVATE) @RequiredArgsConstructor(access = AccessLevel.PRIVATE)
public class BufferedOutputDatastore implements Datastore, Runnable { public class BufferedOutputStorage implements Storage, Runnable {
public static BufferedOutputDatastore wrap(Datastore datastore, long flushTime) { public static BufferedOutputStorage wrap(Storage storage, long flushTime) {
return new BufferedOutputDatastore(datastore, flushTime); return new BufferedOutputStorage(storage, flushTime);
} }
@Getter @Getter
@Delegate(excludes = Exclude.class) @Delegate(excludes = Exclude.class)
private final Datastore backing; private final Storage backing;
private final long flushTime; private final long flushTime;
private final Buffer<User, Boolean> userOutputBuffer = new Buffer<User, Boolean>() { private final Buffer<User, Boolean> userOutputBuffer = new Buffer<User, Boolean>() {
@Override @Override
public Boolean dequeue(User user) { public Boolean dequeue(User user) {
return backing.saveUser(user).getUnchecked(); return backing.saveUser(user).join();
} }
}; };
private final Buffer<Group, Boolean> groupOutputBuffer = new Buffer<Group, Boolean>() { private final Buffer<Group, Boolean> groupOutputBuffer = new Buffer<Group, Boolean>() {
@Override @Override
public Boolean dequeue(Group group) { public Boolean dequeue(Group group) {
return backing.saveGroup(group).getUnchecked(); return backing.saveGroup(group).join();
} }
}; };
private final Buffer<Track, Boolean> trackOutputBuffer = new Buffer<Track, Boolean>() { private final Buffer<Track, Boolean> trackOutputBuffer = new Buffer<Track, Boolean>() {
@Override @Override
public Boolean dequeue(Track track) { public Boolean dequeue(Track track) {
return backing.saveTrack(track).getUnchecked(); return backing.saveTrack(track).join();
} }
}; };
private final Buffer<UserIdentifier, Boolean> uuidDataOutputBuffer = new Buffer<UserIdentifier, Boolean>() { private final Buffer<UserIdentifier, Boolean> uuidDataOutputBuffer = new Buffer<UserIdentifier, Boolean>() {
@Override @Override
protected Boolean dequeue(UserIdentifier userIdentifier) { protected Boolean dequeue(UserIdentifier userIdentifier) {
return backing.saveUUIDData(userIdentifier.getUsername(), userIdentifier.getUuid()).getUnchecked(); return backing.saveUUIDData(userIdentifier.getUsername(), userIdentifier.getUuid()).join();
} }
}; };
@ -92,7 +92,7 @@ public class BufferedOutputDatastore implements Datastore, Runnable {
} }
@Override @Override
public Datastore force() { public Storage force() {
return backing; return backing;
} }
@ -103,31 +103,31 @@ public class BufferedOutputDatastore implements Datastore, Runnable {
} }
@Override @Override
public LPFuture<Boolean> saveUser(User user) { public CompletableFuture<Boolean> saveUser(User user) {
return userOutputBuffer.enqueue(user); return userOutputBuffer.enqueue(user);
} }
@Override @Override
public LPFuture<Boolean> saveGroup(Group group) { public CompletableFuture<Boolean> saveGroup(Group group) {
return groupOutputBuffer.enqueue(group); return groupOutputBuffer.enqueue(group);
} }
@Override @Override
public LPFuture<Boolean> saveTrack(Track track) { public CompletableFuture<Boolean> saveTrack(Track track) {
return trackOutputBuffer.enqueue(track); return trackOutputBuffer.enqueue(track);
} }
@Override @Override
public LPFuture<Boolean> saveUUIDData(String username, UUID uuid) { public CompletableFuture<Boolean> saveUUIDData(String username, UUID uuid) {
return uuidDataOutputBuffer.enqueue(UserIdentifier.of(uuid, username)); return uuidDataOutputBuffer.enqueue(UserIdentifier.of(uuid, username));
} }
private interface Exclude { private interface Exclude {
Datastore force(); Storage force();
LPFuture<Void> shutdown(); CompletableFuture<Void> shutdown();
LPFuture<Boolean> saveUser(User user); CompletableFuture<Boolean> saveUser(User user);
LPFuture<Boolean> saveGroup(Group group); CompletableFuture<Boolean> saveGroup(Group group);
LPFuture<Boolean> saveTrack(Track track); CompletableFuture<Boolean> saveTrack(Track track);
LPFuture<Boolean> saveUUIDData(String username, UUID uuid); CompletableFuture<Boolean> saveUUIDData(String username, UUID uuid);
} }
} }

View File

@ -1,211 +0,0 @@
/*
* 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.api.LogEntry;
import me.lucko.luckperms.api.data.Callback;
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;
public interface Datastore {
String getName();
boolean isAcceptingLogins();
void setAcceptingLogins(boolean acceptingLogins);
/**
* Execute a runnable asynchronously
* @param r the task to run
*/
void doAsync(Runnable r);
/**
* Execute a runnable synchronously
* @param r the task to run
*/
void doSync(Runnable r);
Datastore force();
void init();
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);
default void logAction(LogEntry entry, Callback<Boolean> callback) {
doAsync(() -> {
boolean result = logAction(entry).getUnchecked();
doSync(() -> callback.onComplete(result));
});
}
default void getLog(Callback<Log> callback) {
doAsync(() -> {
Log result = getLog().getUnchecked();
doSync(() -> callback.onComplete(result));
});
}
default void loadUser(UUID uuid, String username, Callback<Boolean> callback) {
doAsync(() -> {
boolean result = loadUser(uuid, username).getUnchecked();
doSync(() -> callback.onComplete(result));
});
}
default void saveUser(User user, Callback<Boolean> callback) {
doAsync(() -> {
boolean result = saveUser(user).getUnchecked();
doSync(() -> callback.onComplete(result));
});
}
default void cleanupUsers(Callback<Boolean> callback) {
doAsync(() -> {
boolean result = cleanupUsers().getUnchecked();
doSync(() -> callback.onComplete(result));
});
}
default void getUniqueUsers(Callback<Set<UUID>> callback) {
doAsync(() -> {
Set<UUID> result = getUniqueUsers().getUnchecked();
doSync(() -> callback.onComplete(result));
});
}
default void createAndLoadGroup(String name, Callback<Boolean> callback) {
doAsync(() -> {
boolean result = createAndLoadGroup(name).getUnchecked();
doSync(() -> callback.onComplete(result));
});
}
default void loadGroup(String name, Callback<Boolean> callback) {
doAsync(() -> {
boolean result = loadGroup(name).getUnchecked();
doSync(() -> callback.onComplete(result));
});
}
default void loadAllGroups(Callback<Boolean> callback) {
doAsync(() -> {
boolean result = loadAllGroups().getUnchecked();
doSync(() -> callback.onComplete(result));
});
}
default void saveGroup(Group group, Callback<Boolean> callback) {
doAsync(() -> {
boolean result = saveGroup(group).getUnchecked();
doSync(() -> callback.onComplete(result));
});
}
default void deleteGroup(Group group, Callback<Boolean> callback) {
doAsync(() -> {
boolean result = deleteGroup(group).getUnchecked();
doSync(() -> callback.onComplete(result));
});
}
default void createAndLoadTrack(String name, Callback<Boolean> callback) {
doAsync(() -> {
boolean result = createAndLoadTrack(name).getUnchecked();
doSync(() -> callback.onComplete(result));
});
}
default void loadTrack(String name, Callback<Boolean> callback) {
doAsync(() -> {
boolean result = loadTrack(name).getUnchecked();
doSync(() -> callback.onComplete(result));
});
}
default void loadAllTracks(Callback<Boolean> callback) {
doAsync(() -> {
boolean result = loadAllTracks().getUnchecked();
doSync(() -> callback.onComplete(result));
});
}
default void saveTrack(Track track, Callback<Boolean> callback) {
doAsync(() -> {
boolean result = saveTrack(track).getUnchecked();
doSync(() -> callback.onComplete(result));
});
}
default void deleteTrack(Track track, Callback<Boolean> callback) {
doAsync(() -> {
boolean result = deleteTrack(track).getUnchecked();
doSync(() -> callback.onComplete(result));
});
}
default void saveUUIDData(String username, UUID uuid, Callback<Boolean> callback) {
doAsync(() -> {
boolean result = saveUUIDData(username, uuid).getUnchecked();
doSync(() -> callback.onComplete(result));
});
}
default void getUUID(String username, Callback<UUID> callback) {
doAsync(() -> {
UUID result = getUUID(username).getUnchecked();
doSync(() -> callback.onComplete(result));
});
}
default void getName(UUID uuid, Callback<String> callback) {
doAsync(() -> {
String result = getName(uuid).getUnchecked();
doSync(() -> callback.onComplete(result));
});
}
}

View File

@ -0,0 +1,66 @@
/*
* 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.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 java.util.Set;
import java.util.UUID;
import java.util.concurrent.CompletableFuture;
/**
* Main interface for all Storage providers.
*/
public interface Storage {
String getName();
boolean isAcceptingLogins();
void setAcceptingLogins(boolean acceptingLogins);
Storage force();
void init();
void shutdown();
CompletableFuture<Boolean> logAction(LogEntry entry);
CompletableFuture<Log> getLog();
CompletableFuture<Boolean> loadUser(UUID uuid, String username);
CompletableFuture<Boolean> saveUser(User user);
CompletableFuture<Boolean> cleanupUsers();
CompletableFuture<Set<UUID>> getUniqueUsers();
CompletableFuture<Boolean> createAndLoadGroup(String name);
CompletableFuture<Boolean> loadGroup(String name);
CompletableFuture<Boolean> loadAllGroups();
CompletableFuture<Boolean> saveGroup(Group group);
CompletableFuture<Boolean> deleteGroup(Group group);
CompletableFuture<Boolean> createAndLoadTrack(String name);
CompletableFuture<Boolean> loadTrack(String name);
CompletableFuture<Boolean> loadAllTracks();
CompletableFuture<Boolean> saveTrack(Track track);
CompletableFuture<Boolean> deleteTrack(Track track);
CompletableFuture<Boolean> saveUUIDData(String username, UUID uuid);
CompletableFuture<UUID> getUUID(String username);
CompletableFuture<String> getName(UUID uuid);
}

View File

@ -37,8 +37,8 @@ import java.util.Set;
public class StorageFactory { public class StorageFactory {
private static final Set<String> TYPES = ImmutableSet.of("json", "yaml", "flatfile", "mongodb", "mysql", "sqlite", "h2"); private static final Set<String> TYPES = ImmutableSet.of("json", "yaml", "flatfile", "mongodb", "mysql", "sqlite", "h2");
public static Datastore getDatastore(LuckPermsPlugin plugin, String defaultMethod) { public static Storage getInstance(LuckPermsPlugin plugin, String defaultMethod) {
Datastore datastore; Storage storage;
plugin.getLog().info("Detecting storage method..."); plugin.getLog().info("Detecting storage method...");
if (plugin.getConfiguration().isSplitStorage()) { if (plugin.getConfiguration().isSplitStorage()) {
@ -63,7 +63,7 @@ public class StorageFactory {
backing.put(type, backingFromString(type, plugin)); backing.put(type, backingFromString(type, plugin));
} }
datastore = AbstractDatastore.wrap(plugin, new SplitBacking(plugin, backing, types)); storage = AbstractStorage.wrap(plugin, new SplitBacking(plugin, backing, types));
} else { } else {
String storageMethod = plugin.getConfiguration().getStorageMethod().toLowerCase(); String storageMethod = plugin.getConfiguration().getStorageMethod().toLowerCase();
@ -72,17 +72,17 @@ public class StorageFactory {
storageMethod = defaultMethod; storageMethod = defaultMethod;
} }
datastore = fromString(storageMethod, plugin); storage = fromString(storageMethod, plugin);
plugin.getLog().info("Using " + datastore.getName() + " as storage method."); plugin.getLog().info("Using " + storage.getName() + " as storage method.");
} }
plugin.getLog().info("Initialising datastore..."); plugin.getLog().info("Initialising datastore...");
datastore.init(); storage.init();
return datastore; return storage;
} }
private static Datastore fromString(String storageMethod, LuckPermsPlugin plugin) { private static Storage fromString(String storageMethod, LuckPermsPlugin plugin) {
return AbstractDatastore.wrap(plugin, backingFromString(storageMethod, plugin)); return AbstractStorage.wrap(plugin, backingFromString(storageMethod, plugin));
} }
private static AbstractBacking backingFromString(String method, LuckPermsPlugin plugin) { private static AbstractBacking backingFromString(String method, LuckPermsPlugin plugin) {

View File

@ -30,30 +30,30 @@ import me.lucko.luckperms.common.data.Log;
import me.lucko.luckperms.common.groups.Group; import me.lucko.luckperms.common.groups.Group;
import me.lucko.luckperms.common.tracks.Track; import me.lucko.luckperms.common.tracks.Track;
import me.lucko.luckperms.common.users.User; import me.lucko.luckperms.common.users.User;
import me.lucko.luckperms.common.utils.LPFuture;
import java.util.Set; import java.util.Set;
import java.util.UUID; import java.util.UUID;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Phaser; import java.util.concurrent.Phaser;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException; import java.util.concurrent.TimeoutException;
/** /**
* A Datastore wrapping that ensures all tasks are completed before {@link Datastore#shutdown()} is called. * A Datastore wrapping that ensures all tasks are completed before {@link Storage#shutdown()} is called.
*/ */
@RequiredArgsConstructor(access = AccessLevel.PRIVATE) @RequiredArgsConstructor(access = AccessLevel.PRIVATE)
public class TolerantDatastore implements Datastore { public class TolerantStorage implements Storage {
public static TolerantDatastore wrap(Datastore datastore) { public static TolerantStorage wrap(Storage storage) {
return new TolerantDatastore(datastore); return new TolerantStorage(storage);
} }
@Delegate(types = Delegated.class) @Delegate(types = Delegated.class)
private final Datastore backing; private final Storage backing;
private final Phaser phaser = new Phaser(); private final Phaser phaser = new Phaser();
@Override @Override
public Datastore force() { public Storage force() {
return this; return this;
} }
@ -70,7 +70,7 @@ public class TolerantDatastore implements Datastore {
} }
@Override @Override
public LPFuture<Boolean> logAction(LogEntry entry) { public CompletableFuture<Boolean> logAction(LogEntry entry) {
phaser.register(); phaser.register();
try { try {
return backing.logAction(entry); return backing.logAction(entry);
@ -80,7 +80,7 @@ public class TolerantDatastore implements Datastore {
} }
@Override @Override
public LPFuture<Log> getLog() { public CompletableFuture<Log> getLog() {
phaser.register(); phaser.register();
try { try {
return backing.getLog(); return backing.getLog();
@ -90,7 +90,7 @@ public class TolerantDatastore implements Datastore {
} }
@Override @Override
public LPFuture<Boolean> loadUser(UUID uuid, String username) { public CompletableFuture<Boolean> loadUser(UUID uuid, String username) {
phaser.register(); phaser.register();
try { try {
return backing.loadUser(uuid, username); return backing.loadUser(uuid, username);
@ -100,7 +100,7 @@ public class TolerantDatastore implements Datastore {
} }
@Override @Override
public LPFuture<Boolean> saveUser(User user) { public CompletableFuture<Boolean> saveUser(User user) {
phaser.register(); phaser.register();
try { try {
return backing.saveUser(user); return backing.saveUser(user);
@ -110,7 +110,7 @@ public class TolerantDatastore implements Datastore {
} }
@Override @Override
public LPFuture<Boolean> cleanupUsers() { public CompletableFuture<Boolean> cleanupUsers() {
phaser.register(); phaser.register();
try { try {
return backing.cleanupUsers(); return backing.cleanupUsers();
@ -120,7 +120,7 @@ public class TolerantDatastore implements Datastore {
} }
@Override @Override
public LPFuture<Set<UUID>> getUniqueUsers() { public CompletableFuture<Set<UUID>> getUniqueUsers() {
phaser.register(); phaser.register();
try { try {
return backing.getUniqueUsers(); return backing.getUniqueUsers();
@ -130,7 +130,7 @@ public class TolerantDatastore implements Datastore {
} }
@Override @Override
public LPFuture<Boolean> createAndLoadGroup(String name) { public CompletableFuture<Boolean> createAndLoadGroup(String name) {
phaser.register(); phaser.register();
try { try {
return backing.createAndLoadGroup(name); return backing.createAndLoadGroup(name);
@ -140,7 +140,7 @@ public class TolerantDatastore implements Datastore {
} }
@Override @Override
public LPFuture<Boolean> loadGroup(String name) { public CompletableFuture<Boolean> loadGroup(String name) {
phaser.register(); phaser.register();
try { try {
return backing.loadGroup(name); return backing.loadGroup(name);
@ -150,7 +150,7 @@ public class TolerantDatastore implements Datastore {
} }
@Override @Override
public LPFuture<Boolean> loadAllGroups() { public CompletableFuture<Boolean> loadAllGroups() {
phaser.register(); phaser.register();
try { try {
return backing.loadAllGroups(); return backing.loadAllGroups();
@ -160,7 +160,7 @@ public class TolerantDatastore implements Datastore {
} }
@Override @Override
public LPFuture<Boolean> saveGroup(Group group) { public CompletableFuture<Boolean> saveGroup(Group group) {
phaser.register(); phaser.register();
try { try {
return backing.saveGroup(group); return backing.saveGroup(group);
@ -170,7 +170,7 @@ public class TolerantDatastore implements Datastore {
} }
@Override @Override
public LPFuture<Boolean> deleteGroup(Group group) { public CompletableFuture<Boolean> deleteGroup(Group group) {
phaser.register(); phaser.register();
try { try {
return backing.deleteGroup(group); return backing.deleteGroup(group);
@ -180,7 +180,7 @@ public class TolerantDatastore implements Datastore {
} }
@Override @Override
public LPFuture<Boolean> createAndLoadTrack(String name) { public CompletableFuture<Boolean> createAndLoadTrack(String name) {
phaser.register(); phaser.register();
try { try {
return backing.createAndLoadTrack(name); return backing.createAndLoadTrack(name);
@ -190,7 +190,7 @@ public class TolerantDatastore implements Datastore {
} }
@Override @Override
public LPFuture<Boolean> loadTrack(String name) { public CompletableFuture<Boolean> loadTrack(String name) {
phaser.register(); phaser.register();
try { try {
return backing.loadTrack(name); return backing.loadTrack(name);
@ -200,7 +200,7 @@ public class TolerantDatastore implements Datastore {
} }
@Override @Override
public LPFuture<Boolean> loadAllTracks() { public CompletableFuture<Boolean> loadAllTracks() {
phaser.register(); phaser.register();
try { try {
return backing.loadAllTracks(); return backing.loadAllTracks();
@ -210,7 +210,7 @@ public class TolerantDatastore implements Datastore {
} }
@Override @Override
public LPFuture<Boolean> saveTrack(Track track) { public CompletableFuture<Boolean> saveTrack(Track track) {
phaser.register(); phaser.register();
try { try {
return backing.saveTrack(track); return backing.saveTrack(track);
@ -220,7 +220,7 @@ public class TolerantDatastore implements Datastore {
} }
@Override @Override
public LPFuture<Boolean> deleteTrack(Track track) { public CompletableFuture<Boolean> deleteTrack(Track track) {
phaser.register(); phaser.register();
try { try {
return backing.deleteTrack(track); return backing.deleteTrack(track);
@ -230,7 +230,7 @@ public class TolerantDatastore implements Datastore {
} }
@Override @Override
public LPFuture<Boolean> saveUUIDData(String username, UUID uuid) { public CompletableFuture<Boolean> saveUUIDData(String username, UUID uuid) {
phaser.register(); phaser.register();
try { try {
return backing.saveUUIDData(username, uuid); return backing.saveUUIDData(username, uuid);
@ -240,7 +240,7 @@ public class TolerantDatastore implements Datastore {
} }
@Override @Override
public LPFuture<UUID> getUUID(String username) { public CompletableFuture<UUID> getUUID(String username) {
phaser.register(); phaser.register();
try { try {
return backing.getUUID(username); return backing.getUUID(username);
@ -250,7 +250,7 @@ public class TolerantDatastore implements Datastore {
} }
@Override @Override
public LPFuture<String> getName(UUID uuid) { public CompletableFuture<String> getName(UUID uuid) {
phaser.register(); phaser.register();
try { try {
return backing.getName(uuid); return backing.getName(uuid);
@ -263,8 +263,6 @@ public class TolerantDatastore implements Datastore {
String getName(); String getName();
boolean isAcceptingLogins(); boolean isAcceptingLogins();
void setAcceptingLogins(boolean b); void setAcceptingLogins(boolean b);
void doAsync(Runnable r);
void doSync(Runnable r);
void init(); void init();
} }
} }

View File

@ -38,6 +38,8 @@ import java.util.UUID;
@RequiredArgsConstructor(access = AccessLevel.PROTECTED) @RequiredArgsConstructor(access = AccessLevel.PROTECTED)
public abstract class AbstractBacking { public abstract class AbstractBacking {
@Getter
protected final LuckPermsPlugin plugin; protected final LuckPermsPlugin plugin;
@Getter @Getter
@ -47,22 +49,6 @@ public abstract class AbstractBacking {
@Setter @Setter
private boolean acceptingLogins = false; 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 init();
public abstract void shutdown(); public abstract void shutdown();
public abstract boolean logAction(LogEntry entry); public abstract boolean logAction(LogEntry entry);

View File

@ -24,7 +24,6 @@ package me.lucko.luckperms.common.users;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import me.lucko.luckperms.api.Node; import me.lucko.luckperms.api.Node;
import me.lucko.luckperms.api.data.Callback;
import me.lucko.luckperms.common.LuckPermsPlugin; import me.lucko.luckperms.common.LuckPermsPlugin;
import me.lucko.luckperms.common.utils.AbstractManager; import me.lucko.luckperms.common.utils.AbstractManager;
import me.lucko.luckperms.common.utils.Identifiable; import me.lucko.luckperms.common.utils.Identifiable;
@ -81,7 +80,7 @@ public class UserManager extends AbstractManager<UserIdentifier, User> {
} catch (ObjectAlreadyHasException ignored) {} } catch (ObjectAlreadyHasException ignored) {}
if (save) { if (save) {
plugin.getDatastore().saveUser(user, Callback.empty()); plugin.getStorage().saveUser(user);
} }
return true; return true;
@ -134,7 +133,7 @@ public class UserManager extends AbstractManager<UserIdentifier, User> {
plugin.doAsync(() -> { plugin.doAsync(() -> {
for (UUID uuid : players) { for (UUID uuid : players) {
UUID internal = plugin.getUuidCache().getUUID(uuid); UUID internal = plugin.getUuidCache().getUUID(uuid);
plugin.getDatastore().loadUser(internal, "null").getUnchecked(); plugin.getStorage().loadUser(internal, "null").join();
User user = get(internal); User user = get(internal);
user.getRefreshBuffer().request(); user.getRefreshBuffer().request();
} }

View File

@ -1,72 +0,0 @@
/*
* 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.CountDownLatch;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
/**
* Basic Future implementation
* @param <R> the return type
*/
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();
}
}
}

View File

@ -23,7 +23,6 @@
package me.lucko.luckperms.common.utils; package me.lucko.luckperms.common.utils;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
import me.lucko.luckperms.api.data.Callback;
import me.lucko.luckperms.api.event.events.UserFirstLoginEvent; import me.lucko.luckperms.api.event.events.UserFirstLoginEvent;
import me.lucko.luckperms.common.LuckPermsPlugin; import me.lucko.luckperms.common.LuckPermsPlugin;
import me.lucko.luckperms.common.core.UuidCache; import me.lucko.luckperms.common.core.UuidCache;
@ -44,26 +43,26 @@ public class AbstractListener {
final UuidCache cache = plugin.getUuidCache(); final UuidCache cache = plugin.getUuidCache();
if (!cache.isOnlineMode()) { if (!cache.isOnlineMode()) {
UUID uuid = plugin.getDatastore().force().getUUID(username).getUnchecked(); UUID uuid = plugin.getStorage().force().getUUID(username).join();
if (uuid != null) { if (uuid != null) {
cache.addToCache(u, uuid); cache.addToCache(u, uuid);
} else { } else {
// No previous data for this player // No previous data for this player
plugin.getApiProvider().fireEventAsync(new UserFirstLoginEvent(u, username)); plugin.getApiProvider().fireEventAsync(new UserFirstLoginEvent(u, username));
cache.addToCache(u, u); cache.addToCache(u, u);
plugin.getDatastore().force().saveUUIDData(username, u, Callback.empty()); plugin.getStorage().force().saveUUIDData(username, u);
} }
} else { } else {
UUID uuid = plugin.getDatastore().force().getUUID(username).getUnchecked(); UUID uuid = plugin.getStorage().force().getUUID(username).join();
if (uuid == null) { if (uuid == null) {
plugin.getApiProvider().fireEventAsync(new UserFirstLoginEvent(u, username)); plugin.getApiProvider().fireEventAsync(new UserFirstLoginEvent(u, username));
} }
// Online mode, no cache needed. This is just for name -> uuid lookup. // Online mode, no cache needed. This is just for name -> uuid lookup.
plugin.getDatastore().force().saveUUIDData(username, u, Callback.empty()); plugin.getStorage().force().saveUUIDData(username, u);
} }
plugin.getDatastore().force().loadUser(cache.getUUID(u), username).getUnchecked(); plugin.getStorage().force().loadUser(cache.getUUID(u), username).join();
User user = plugin.getUserManager().get(cache.getUUID(u)); User user = plugin.getUserManager().get(cache.getUUID(u));
if (user == null) { if (user == null) {
plugin.getLog().warn("Failed to load user: " + username); plugin.getLog().warn("Failed to load user: " + username);
@ -78,7 +77,7 @@ public class AbstractListener {
// If they were given a default, persist the new assignments back to the storage. // If they were given a default, persist the new assignments back to the storage.
if (save) { if (save) {
plugin.getDatastore().force().saveUser(user).getUnchecked(); plugin.getStorage().force().saveUser(user).join();
} }
user.setupData(false); // Pretty nasty calculation call. Sets up the caching system so data is ready when the user joins. user.setupData(false); // Pretty nasty calculation call. Sets up the caching system so data is ready when the user joins.

View File

@ -27,6 +27,7 @@ import lombok.*;
import java.util.LinkedList; import java.util.LinkedList;
import java.util.List; import java.util.List;
import java.util.ListIterator; import java.util.ListIterator;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.locks.ReentrantLock; import java.util.concurrent.locks.ReentrantLock;
/** /**
@ -42,7 +43,7 @@ public abstract class Buffer<T, R> implements Runnable {
private final ReentrantLock lock = new ReentrantLock(); private final ReentrantLock lock = new ReentrantLock();
private final List<BufferedObject<T, R>> buffer = new LinkedList<>(); private final List<BufferedObject<T, R>> buffer = new LinkedList<>();
public LPFuture<R> enqueue(@NonNull T t) { public CompletableFuture<R> enqueue(@NonNull T t) {
lock.lock(); lock.lock();
try { try {
ListIterator<BufferedObject<T, R>> it = buffer.listIterator(); ListIterator<BufferedObject<T, R>> it = buffer.listIterator();
@ -60,7 +61,7 @@ public abstract class Buffer<T, R> implements Runnable {
} }
if (o == null) { if (o == null) {
o = new BufferedObject<>(System.currentTimeMillis(), t, new AbstractFuture<R>()); o = new BufferedObject<>(System.currentTimeMillis(), t, new CompletableFuture<R>());
} else { } else {
o.setBufferTime(System.currentTimeMillis()); o.setBufferTime(System.currentTimeMillis());
} }
@ -111,7 +112,7 @@ public abstract class Buffer<T, R> implements Runnable {
@Setter @Setter
private long bufferTime; private long bufferTime;
private final T object; private final T object;
private final AbstractFuture<R> future; private final CompletableFuture<R> future;
} }
} }

View File

@ -26,8 +26,9 @@ import lombok.Getter;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import java.lang.ref.WeakReference; import java.lang.ref.WeakReference;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Executor;
import java.util.concurrent.locks.ReentrantLock; import java.util.concurrent.locks.ReentrantLock;
import java.util.function.Consumer;
import java.util.function.Supplier; import java.util.function.Supplier;
/** /**
@ -41,12 +42,12 @@ import java.util.function.Supplier;
@RequiredArgsConstructor @RequiredArgsConstructor
public abstract class BufferedRequest<T> { public abstract class BufferedRequest<T> {
private final long bufferTimeMillis; private final long bufferTimeMillis;
private final Consumer<Runnable> executor; private final Executor executor;
private WeakReference<Processor<T>> processor = null; private WeakReference<Processor<T>> processor = null;
private ReentrantLock lock = new ReentrantLock(); private ReentrantLock lock = new ReentrantLock();
public LPFuture<T> request() { public CompletableFuture<T> request() {
lock.lock(); lock.lock();
try { try {
if (processor != null) { if (processor != null) {
@ -57,7 +58,7 @@ public abstract class BufferedRequest<T> {
} }
Processor<T> p = new Processor<>(bufferTimeMillis, this::perform); Processor<T> p = new Processor<>(bufferTimeMillis, this::perform);
executor.accept(p); executor.execute(p);
processor = new WeakReference<>(p); processor = new WeakReference<>(p);
return p.get(); return p.get();
@ -82,7 +83,7 @@ public abstract class BufferedRequest<T> {
private final ReentrantLock lock = new ReentrantLock(); private final ReentrantLock lock = new ReentrantLock();
private long executionTime; private long executionTime;
private final AbstractFuture<R> future = new AbstractFuture<>(); private final CompletableFuture<R> future = new CompletableFuture<R>();
@Override @Override
public void run() { public void run() {
@ -116,11 +117,11 @@ public abstract class BufferedRequest<T> {
future.complete(result); future.complete(result);
} }
public LPFuture<R> get() { public CompletableFuture<R> get() {
return future; return future;
} }
public LPFuture<R> getAndExtend() { public CompletableFuture<R> getAndExtend() {
lock.lock(); lock.lock();
try { try {
executionTime = System.currentTimeMillis() + delayMillis; executionTime = System.currentTimeMillis() + delayMillis;

View File

@ -21,16 +21,16 @@ does-not-have-temp-permission: "{0} does not have this permission set temporaril
user-not-found: "&bUser could not be found." user-not-found: "&bUser could not be found."
user-save-success: "&7(User data was saved to the datastore)" user-save-success: "&7(User data was saved to storage)"
user-save-error: "There was an error whilst saving the user." user-save-error: "There was an error whilst saving the user."
user-create-fail: "There was an error whilst creating a new user." user-create-fail: "There was an error whilst creating a new user."
group-not-found: "&bGroup could not be found." group-not-found: "&bGroup could not be found."
group-save-success: "&7(Group data was saved to the datastore)" group-save-success: "&7(Group data was saved to storage)"
group-save-error: "There was an error whilst saving the group." group-save-error: "There was an error whilst saving the group."
track-not-found: "&bTrack could not be found." track-not-found: "&bTrack could not be found."
track-save-success: "&7(Track data was saved to the datastore)" track-save-success: "&7(Track data was saved to storage)"
track-save-error: "There was an error whilst saving the track." track-save-error: "There was an error whilst saving the track."

View File

@ -6,7 +6,7 @@
<groupId>me.lucko.luckperms</groupId> <groupId>me.lucko.luckperms</groupId>
<artifactId>luckperms</artifactId> <artifactId>luckperms</artifactId>
<version>2.13-SNAPSHOT</version> <version>2.14-SNAPSHOT</version>
<modules> <modules>
<module>common</module> <module>common</module>
<module>api</module> <module>api</module>
@ -38,7 +38,7 @@
<properties> <properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<release.version>2.13</release.version> <release.version>2.14</release.version>
</properties> </properties>
<distributionManagement> <distributionManagement>

View File

@ -5,7 +5,7 @@
<parent> <parent>
<artifactId>luckperms</artifactId> <artifactId>luckperms</artifactId>
<groupId>me.lucko.luckperms</groupId> <groupId>me.lucko.luckperms</groupId>
<version>2.13-SNAPSHOT</version> <version>2.14-SNAPSHOT</version>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>

View File

@ -43,7 +43,7 @@ import me.lucko.luckperms.common.groups.GroupManager;
import me.lucko.luckperms.common.messaging.RedisMessaging; import me.lucko.luckperms.common.messaging.RedisMessaging;
import me.lucko.luckperms.common.runnables.ExpireTemporaryTask; import me.lucko.luckperms.common.runnables.ExpireTemporaryTask;
import me.lucko.luckperms.common.runnables.UpdateTask; import me.lucko.luckperms.common.runnables.UpdateTask;
import me.lucko.luckperms.common.storage.Datastore; import me.lucko.luckperms.common.storage.Storage;
import me.lucko.luckperms.common.storage.StorageFactory; import me.lucko.luckperms.common.storage.StorageFactory;
import me.lucko.luckperms.common.tracks.TrackManager; import me.lucko.luckperms.common.tracks.TrackManager;
import me.lucko.luckperms.common.users.UserManager; import me.lucko.luckperms.common.users.UserManager;
@ -77,6 +77,7 @@ import java.io.File;
import java.nio.file.Path; import java.nio.file.Path;
import java.util.*; import java.util.*;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Executor;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors; import java.util.stream.Collectors;
@ -105,6 +106,8 @@ public class LPSpongePlugin implements LuckPermsPlugin {
private Path configDir; private Path configDir;
private Scheduler scheduler = Sponge.getScheduler(); private Scheduler scheduler = Sponge.getScheduler();
private Executor syncExecutor = Sponge.getScheduler().createSyncExecutor(this);
private Executor asyncExecutor = Sponge.getScheduler().createAsyncExecutor(this);
private LPTimings timings; private LPTimings timings;
private final Set<UUID> ignoringLogs = ConcurrentHashMap.newKeySet(); private final Set<UUID> ignoringLogs = ConcurrentHashMap.newKeySet();
@ -112,7 +115,7 @@ public class LPSpongePlugin implements LuckPermsPlugin {
private UserManager userManager; private UserManager userManager;
private GroupManager groupManager; private GroupManager groupManager;
private TrackManager trackManager; private TrackManager trackManager;
private Datastore datastore; private Storage storage;
private RedisMessaging redisMessaging = null; private RedisMessaging redisMessaging = null;
private UuidCache uuidCache; private UuidCache uuidCache;
private ApiProvider apiProvider; private ApiProvider apiProvider;
@ -141,7 +144,7 @@ public class LPSpongePlugin implements LuckPermsPlugin {
Sponge.getEventManager().registerListeners(this, new SpongeListener(this)); Sponge.getEventManager().registerListeners(this, new SpongeListener(this));
// initialise datastore // initialise datastore
datastore = StorageFactory.getDatastore(this, "h2"); storage = StorageFactory.getInstance(this, "h2");
// initialise redis // initialise redis
if (getConfiguration().isRedisEnabled()) { if (getConfiguration().isRedisEnabled()) {
@ -228,7 +231,7 @@ public class LPSpongePlugin implements LuckPermsPlugin {
@Listener @Listener
public void onDisable(GameStoppingServerEvent event) { public void onDisable(GameStoppingServerEvent event) {
getLog().info("Closing datastore..."); getLog().info("Closing datastore...");
datastore.shutdown(); storage.shutdown();
if (redisMessaging != null) { if (redisMessaging != null) {
getLog().info("Closing redis..."); getLog().info("Closing redis...");

View File

@ -52,7 +52,7 @@ public class SpongeListener extends AbstractListener {
@Listener(order = Order.EARLY) @Listener(order = Order.EARLY)
public void onClientAuth(ClientConnectionEvent.Auth e) { public void onClientAuth(ClientConnectionEvent.Auth e) {
if (!plugin.getDatastore().isAcceptingLogins()) { if (!plugin.getStorage().isAcceptingLogins()) {
/* Datastore is disabled, prevent players from joining the server /* Datastore is disabled, prevent players from joining the server
Just don't load their data, they will be kicked at login */ Just don't load their data, they will be kicked at login */
return; return;

View File

@ -89,10 +89,10 @@ public class MigrationPermissionManager extends SubCommand<Object> {
groupCount++; groupCount++;
// Make a LuckPerms group for the one being migrated // Make a LuckPerms group for the one being migrated
plugin.getDatastore().createAndLoadGroup(pmGroup.getIdentifier().toLowerCase()).getUnchecked(); plugin.getStorage().createAndLoadGroup(pmGroup.getIdentifier().toLowerCase()).join();
Group group = plugin.getGroupManager().get(pmGroup.getIdentifier().toLowerCase()); Group group = plugin.getGroupManager().get(pmGroup.getIdentifier().toLowerCase());
migrateSubject(pmGroup, group); migrateSubject(pmGroup, group);
plugin.getDatastore().saveGroup(group); plugin.getStorage().saveGroup(group);
} }
log.info("PermissionManager Migration: Migrated " + groupCount + " groups"); log.info("PermissionManager Migration: Migrated " + groupCount + " groups");
@ -117,10 +117,10 @@ public class MigrationPermissionManager extends SubCommand<Object> {
} }
// Make a LuckPerms user for the one being migrated // Make a LuckPerms user for the one being migrated
plugin.getDatastore().loadUser(uuid, "null").getUnchecked(); plugin.getStorage().loadUser(uuid, "null").join();
User user = plugin.getUserManager().get(uuid); User user = plugin.getUserManager().get(uuid);
migrateSubject(pmUser, user); migrateSubject(pmUser, user);
plugin.getDatastore().saveUser(user); plugin.getStorage().saveUser(user);
plugin.getUserManager().cleanup(user); plugin.getUserManager().cleanup(user);
} }

View File

@ -69,10 +69,10 @@ public class MigrationPermissionsEx extends SubCommand<Object> {
groupCount++; groupCount++;
// Make a LuckPerms group for the one being migrated // Make a LuckPerms group for the one being migrated
plugin.getDatastore().createAndLoadGroup(pexGroup.getIdentifier().toLowerCase()).getUnchecked(); plugin.getStorage().createAndLoadGroup(pexGroup.getIdentifier().toLowerCase()).join();
Group group = plugin.getGroupManager().get(pexGroup.getIdentifier().toLowerCase()); Group group = plugin.getGroupManager().get(pexGroup.getIdentifier().toLowerCase());
migrateSubject(pexGroup, group); migrateSubject(pexGroup, group);
plugin.getDatastore().saveGroup(group); plugin.getStorage().saveGroup(group);
} }
log.info("PermissionsEx Migration: Migrated " + groupCount + " groups"); log.info("PermissionsEx Migration: Migrated " + groupCount + " groups");
@ -88,10 +88,10 @@ public class MigrationPermissionsEx extends SubCommand<Object> {
} }
// Make a LuckPerms user for the one being migrated // Make a LuckPerms user for the one being migrated
plugin.getDatastore().loadUser(uuid, "null").getUnchecked(); plugin.getStorage().loadUser(uuid, "null").join();
User user = plugin.getUserManager().get(uuid); User user = plugin.getUserManager().get(uuid);
migrateSubject(pexUser, user); migrateSubject(pexUser, user);
plugin.getDatastore().saveUser(user); plugin.getStorage().saveUser(user);
plugin.getUserManager().cleanup(user); plugin.getUserManager().cleanup(user);
} }

View File

@ -59,10 +59,12 @@ public class LuckPermsSubjectData implements SubjectData {
private void objectSave(PermissionHolder t) { private void objectSave(PermissionHolder t) {
if (t instanceof User) { if (t instanceof User) {
service.getPlugin().getDatastore().saveUser(((User) t), b -> ((User) t).getRefreshBuffer().request()); service.getPlugin().getStorage().saveUser(((User) t))
.thenRunAsync(() -> ((User) t).getRefreshBuffer().request(), service.getPlugin().getAsyncExecutor());
} }
if (t instanceof Group) { if (t instanceof Group) {
service.getPlugin().getDatastore().saveGroup(((Group) t), b -> service.getPlugin().getUpdateTaskBuffer().request()); service.getPlugin().getStorage().saveGroup((Group) t)
.thenRunAsync(() -> service.getPlugin().getUpdateTaskBuffer().request(), service.getPlugin().getAsyncExecutor());
} }
} }

View File

@ -97,7 +97,7 @@ public class GroupCollection implements SubjectCollection {
if (!manager.isLoaded(id)) { if (!manager.isLoaded(id)) {
service.getPlugin().getLog().warn("Group Subject '" + id + "' was requested, but is not loaded in memory. Loading it from storage now."); service.getPlugin().getLog().warn("Group Subject '" + id + "' was requested, but is not loaded in memory. Loading it from storage now.");
long startTime = System.currentTimeMillis(); long startTime = System.currentTimeMillis();
service.getPlugin().getDatastore().createAndLoadGroup(id).getUnchecked(); service.getPlugin().getStorage().createAndLoadGroup(id).join();
service.getPlugin().getLog().warn("Loading '" + id + "' took " + (System.currentTimeMillis() - startTime) + " ms."); service.getPlugin().getLog().warn("Loading '" + id + "' took " + (System.currentTimeMillis() - startTime) + " ms.");
} }

View File

@ -109,7 +109,7 @@ public class UserCollection implements SubjectCollection {
if (!manager.isLoaded(UserIdentifier.of(u, null))) { if (!manager.isLoaded(UserIdentifier.of(u, null))) {
service.getPlugin().getLog().warn("User Subject '" + u + "' was requested, but is not loaded in memory. Loading them from storage now."); service.getPlugin().getLog().warn("User Subject '" + u + "' was requested, but is not loaded in memory. Loading them from storage now.");
long startTime = System.currentTimeMillis(); long startTime = System.currentTimeMillis();
service.getPlugin().getDatastore().loadUser(u, "null").getUnchecked(); service.getPlugin().getStorage().loadUser(u, "null").join();
service.getPlugin().getLog().warn("Loading '" + u + "' took " + (System.currentTimeMillis() - startTime) + " ms."); service.getPlugin().getLog().warn("Loading '" + u + "' took " + (System.currentTimeMillis() - startTime) + " ms.");
} }