Finish the buffering refactor - still WIP. Towards #32

This commit is contained in:
Luck 2016-10-21 18:34:53 +01:00
parent 37fc00cce8
commit be7d914e39
No known key found for this signature in database
GPG Key ID: EFA9B3EC5FD90F8B
37 changed files with 143 additions and 220 deletions

View File

@ -142,7 +142,7 @@ public class LPBukkitPlugin extends JavaPlugin implements LuckPermsPlugin {
}
final LPBukkitPlugin i = this;
updateTaskBuffer = new BufferedRequest<Void>(5000L, this::doAsync) {
updateTaskBuffer = new BufferedRequest<Void>(6000L, this::doAsync) {
@Override
protected Void perform() {
getServer().getScheduler().runTaskAsynchronously(i, new UpdateTask(i));

View File

@ -130,12 +130,13 @@ public class VaultPermissionHook extends Permission {
*/
void save(PermissionHolder holder) {
if (holder instanceof User) {
((User) holder).refreshPermissions();
plugin.getDatastore().saveUser(((User) holder));
plugin.getDatastore().saveUser(((User) holder), b -> {
((User) holder).getRefreshBuffer().request();
});
}
if (holder instanceof Group) {
plugin.getDatastore().saveGroup(((Group) holder));
plugin.runUpdateTask();
plugin.getDatastore().saveGroup(((Group) holder), b -> plugin.getUpdateTaskBuffer().request());
}
}

View File

@ -102,7 +102,7 @@ public class BungeeListener extends AbstractListener implements Listener {
// No previous data for this player
plugin.getApiProvider().fireEventAsync(new UserFirstLoginEvent(c.getUniqueId(), c.getName()));
cache.addToCache(c.getUniqueId(), c.getUniqueId());
plugin.getDatastore().saveUUIDData(c.getName(), c.getUniqueId());
plugin.getDatastore().force().saveUUIDData(c.getName(), c.getUniqueId()).getOrDefault(false);
}
} else {
UUID uuid = plugin.getDatastore().getUUID(c.getName()).getOrDefault(null);
@ -111,12 +111,12 @@ public class BungeeListener extends AbstractListener implements Listener {
}
// Online mode, no cache needed. This is just for name -> uuid lookup.
plugin.getDatastore().saveUUIDData(c.getName(), c.getUniqueId());
plugin.getDatastore().force().saveUUIDData(c.getName(), c.getUniqueId()).getOrDefault(false);
}
// 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.
plugin.getDatastore().loadUser(cache.getUUID(c.getUniqueId()), c.getName());
plugin.getDatastore().force().loadUser(cache.getUUID(c.getUniqueId()), c.getName()).getOrDefault(false);
User user = plugin.getUserManager().get(cache.getUUID(c.getUniqueId()));
if (user == null) {
plugin.getLog().warn("Failed to load user: " + c.getName());

View File

@ -46,6 +46,7 @@ import me.lucko.luckperms.common.storage.Datastore;
import me.lucko.luckperms.common.storage.StorageFactory;
import me.lucko.luckperms.common.tracks.TrackManager;
import me.lucko.luckperms.common.users.UserManager;
import me.lucko.luckperms.common.utils.BufferedRequest;
import me.lucko.luckperms.common.utils.LocaleManager;
import me.lucko.luckperms.common.utils.LogFactory;
import net.md_5.bungee.api.config.ServerInfo;
@ -74,6 +75,7 @@ public class LPBungeePlugin extends Plugin implements LuckPermsPlugin {
private LocaleManager localeManager;
private ContextManager<ProxiedPlayer> contextManager;
private CalculatorFactory calculatorFactory;
private BufferedRequest<Void> updateTaskBuffer;
@Override
public void onEnable() {
@ -121,6 +123,15 @@ public class LPBungeePlugin extends Plugin implements LuckPermsPlugin {
contextManager.registerCalculator(serverCalculator);
contextManager.registerCalculator(new ServerCalculator<>(getConfiguration().getServer()));
final LPBungeePlugin i = this;
updateTaskBuffer = new BufferedRequest<Void>(6000L, this::doAsync) {
@Override
protected Void perform() {
doAsync(new UpdateTask(i));
return null;
}
};
int mins = getConfiguration().getSyncTime();
if (mins > 0) {
getProxy().getScheduler().schedule(this, new UpdateTask(this), mins, mins, TimeUnit.MINUTES);
@ -254,11 +265,6 @@ public class LPBungeePlugin extends Plugin implements LuckPermsPlugin {
.isPresent();
}
@Override
public void runUpdateTask() {
doAsync(new UpdateTask(this));
}
@Override
public void doAsync(Runnable r) {
getProxy().getScheduler().runAsync(this, r);

View File

@ -64,7 +64,7 @@ public class ApiProvider implements LuckPermsApi {
@Override
public void runUpdateTask() {
plugin.runUpdateTask();
plugin.getUpdateTaskBuffer().request();
}
@Override

View File

@ -79,7 +79,7 @@ public class UserLink extends PermissionHolderLink implements User {
@Override
public void refreshPermissions() {
master.refreshPermissions();
master.getRefreshBuffer().requestDirectly();
}
@Override

View File

@ -168,7 +168,7 @@ public abstract class SubCommand<T> {
Message.USER_SAVE_ERROR.send(sender);
}
user.refreshPermissions();
user.getRefreshBuffer().request().getOrDefault(null);
}
public static void save(Group group, Sender sender, LuckPermsPlugin plugin) {
@ -178,7 +178,7 @@ public abstract class SubCommand<T> {
Message.GROUP_SAVE_ERROR.send(sender);
}
plugin.runUpdateTask();
plugin.getUpdateTaskBuffer().request();
}
public static void save(Track track, Sender sender, LuckPermsPlugin plugin) {
@ -188,6 +188,6 @@ public abstract class SubCommand<T> {
Message.TRACK_SAVE_ERROR.send(sender);
}
plugin.runUpdateTask();
plugin.getUpdateTaskBuffer().request();
}
}

View File

@ -63,7 +63,6 @@ public class CreateGroup extends SingleMainCommand {
Message.CREATE_SUCCESS.send(sender, groupName);
LogEntry.build().actor(sender).actedName(groupName).type('G').action("create").build().submit(plugin, sender);
plugin.runUpdateTask();
return CommandResult.SUCCESS;
}
}

View File

@ -73,7 +73,7 @@ public class DeleteGroup extends SingleMainCommand {
Message.DELETE_SUCCESS.send(sender, group.getDisplayName());
LogEntry.build().actor(sender).actedName(groupName).type('G').action("delete").build().submit(plugin, sender);
plugin.runUpdateTask();
plugin.getUpdateTaskBuffer().request();
return CommandResult.SUCCESS;
}

View File

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

View File

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

View File

@ -73,7 +73,7 @@ public class MigrationGroupManager extends SubCommand<Object> {
}
for (Group g : gg.getGroupList()) {
plugin.getDatastore().createAndLoadGroup(g.getName().toLowerCase());
plugin.getDatastore().createAndLoadGroup(g.getName().toLowerCase()).getOrDefault(false);
me.lucko.luckperms.common.groups.Group group = plugin.getGroupManager().get(g.getName().toLowerCase());
try {
LogEntry.build()
@ -121,7 +121,7 @@ public class MigrationGroupManager extends SubCommand<Object> {
}
}
plugin.getDatastore().saveGroup(group);
plugin.getDatastore().saveGroup(group).getOrDefault(false);
}
Map<UUID, Map<Map.Entry<String, String>, Boolean>> users = new HashMap<>();
@ -202,7 +202,7 @@ public class MigrationGroupManager extends SubCommand<Object> {
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()) {
plugin.getDatastore().createAndLoadGroup(e.getKey());
plugin.getDatastore().createAndLoadGroup(e.getKey()).getOrDefault(false);
me.lucko.luckperms.common.groups.Group group = plugin.getGroupManager().get(e.getKey());
try {
LogEntry.build()
@ -241,11 +241,11 @@ public class MigrationGroupManager extends SubCommand<Object> {
}
}
plugin.getDatastore().saveGroup(group);
plugin.getDatastore().saveGroup(group).getOrDefault(false);
}
for (Map.Entry<UUID, Map<Map.Entry<String, String>, Boolean>> e : users.entrySet()) {
plugin.getDatastore().loadUser(e.getKey(), "null");
plugin.getDatastore().loadUser(e.getKey(), "null").getOrDefault(false);
me.lucko.luckperms.common.users.User user = plugin.getUserManager().get(e.getKey());
for (Map.Entry<Map.Entry<String, String>, Boolean> n : e.getValue().entrySet()) {
@ -275,7 +275,7 @@ public class MigrationGroupManager extends SubCommand<Object> {
}
}
plugin.getDatastore().saveUser(user);
plugin.getDatastore().saveUser(user).getOrDefault(false);
plugin.getUserManager().cleanup(user);
}

View File

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

View File

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

View File

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

View File

@ -124,7 +124,7 @@ public class ExportCommand extends SingleMainCommand {
int userCount = 0;
for (UUID uuid : users) {
userCount++;
plugin.getDatastore().loadUser(uuid, "null");
plugin.getDatastore().loadUser(uuid, "null").getOrDefault(false);
User user = plugin.getUserManager().get(uuid);
boolean inDefault = false;

View File

@ -38,8 +38,9 @@ public class SyncCommand extends SingleMainCommand {
@Override
protected CommandResult execute(LuckPermsPlugin plugin, Sender sender, List<String> args, String label) {
Message.UPDATE_TASK_RUN.send(sender);
plugin.runUpdateTask();
Message.UPDATE_TASK_REQUEST.send(sender);
plugin.getUpdateTaskBuffer().request().getOrDefault(null);
Message.UPDATE_TASK_COMPLETE.send(sender);
return CommandResult.SUCCESS;
}
}

View File

@ -63,7 +63,6 @@ public class CreateTrack extends SingleMainCommand {
Message.CREATE_SUCCESS.send(sender, trackName);
LogEntry.build().actor(sender).actedName(trackName).type('T').action("create").build().submit(plugin, sender);
plugin.runUpdateTask();
return CommandResult.SUCCESS;
}
}

View File

@ -67,7 +67,7 @@ public class DeleteTrack extends SingleMainCommand {
Message.DELETE_SUCCESS.send(sender, trackName);
LogEntry.build().actor(sender).actedName(trackName).type('T').action("delete").build().submit(plugin, sender);
plugin.runUpdateTask();
plugin.getUpdateTaskBuffer().request();
return CommandResult.SUCCESS;
}

View File

@ -64,7 +64,7 @@ public class BulkEditGroup extends SubCommand<Datastore> {
Set<UUID> uuids = datastore.getUniqueUsers().getOrDefault(null);
for (UUID u : uuids) {
plugin.getDatastore().loadUser(u, "null");
plugin.getDatastore().loadUser(u, "null").getOrDefault(false);
User user = plugin.getUserManager().get(u);
if (user == null) {
continue;
@ -138,7 +138,7 @@ public class BulkEditGroup extends SubCommand<Datastore> {
});
plugin.getUserManager().cleanup(user);
plugin.getDatastore().saveUser(user);
plugin.getDatastore().saveUser(user).getOrDefault(false);
}
Message.BULK_CHANGE_SUCCESS.send(sender, uuids.size());

View File

@ -64,7 +64,7 @@ public class BulkEditPermission extends SubCommand<Datastore> {
Set<UUID> uuids = datastore.getUniqueUsers().getOrDefault(null);
for (UUID u : uuids) {
plugin.getDatastore().loadUser(u, "null");
plugin.getDatastore().loadUser(u, "null").getOrDefault(false);
User user = plugin.getUserManager().get(u);
if (user == null) {
continue;
@ -128,7 +128,7 @@ public class BulkEditPermission extends SubCommand<Datastore> {
});
plugin.getUserManager().cleanup(user);
plugin.getDatastore().saveUser(user);
plugin.getDatastore().saveUser(user).getOrDefault(false);
}
Message.BULK_CHANGE_SUCCESS.send(sender, uuids.size());

View File

@ -108,7 +108,8 @@ public enum Message {
TRACKS_LOAD_ERROR("An unexpected error occurred. Unable to load all tracks.", true),
TRACK_EMPTY("The track cannot be used as it is empty or contains only one group.", true),
UPDATE_TASK_RUN("&bRunning update task for all online users.", true),
UPDATE_TASK_REQUEST("&bUpdate task scheduled.", true),
UPDATE_TASK_COMPLETE("&aUpdate task finished.", true),
INFO(
"{PREFIX}&2Running &bLuckPerms v{0}&2 by &bLuck&2." + "\n" +
"{PREFIX}&f-> &3Platform: &f{1}" + "\n" +

View File

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

View File

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

View File

@ -25,8 +25,7 @@ package me.lucko.luckperms.common.storage;
import lombok.AccessLevel;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import me.lucko.luckperms.api.LogEntry;
import me.lucko.luckperms.common.data.Log;
import lombok.experimental.Delegate;
import me.lucko.luckperms.common.groups.Group;
import me.lucko.luckperms.common.tracks.Track;
import me.lucko.luckperms.common.users.User;
@ -34,7 +33,6 @@ import me.lucko.luckperms.common.users.UserIdentifier;
import me.lucko.luckperms.common.utils.Buffer;
import me.lucko.luckperms.common.utils.LPFuture;
import java.util.Set;
import java.util.UUID;
@RequiredArgsConstructor(access = AccessLevel.PRIVATE)
@ -44,42 +42,36 @@ public class BufferedOutputDatastore implements Datastore, Runnable {
}
@Getter
@Delegate(excludes = Exclude.class)
private final Datastore backing;
private final long flushTime;
private final Buffer<LogEntry, Boolean> logOutputBuffer = new Buffer<LogEntry, Boolean>() {
@Override
public Boolean dequeue(LogEntry logEntry) {
return backing.logAction(logEntry).getOrDefault(false);
}
};
private final Buffer<User, Boolean> userOutputBuffer = new Buffer<User, Boolean>() {
@Override
public Boolean dequeue(User user) {
return saveUser(user).getOrDefault(false);
return backing.saveUser(user).getOrDefault(false);
}
};
private final Buffer<Group, Boolean> groupOutputBuffer = new Buffer<Group, Boolean>() {
@Override
public Boolean dequeue(Group group) {
return saveGroup(group).getOrDefault(false);
return backing.saveGroup(group).getOrDefault(false);
}
};
private final Buffer<Track, Boolean> trackOutputBuffer = new Buffer<Track, Boolean>() {
@Override
public Boolean dequeue(Track track) {
return saveTrack(track).getOrDefault(false);
return backing.saveTrack(track).getOrDefault(false);
}
};
private final Buffer<UserIdentifier, Boolean> uuidDataOutputBuffer = new Buffer<UserIdentifier, Boolean>() {
@Override
protected Boolean dequeue(UserIdentifier userIdentifier) {
return saveUUIDData(userIdentifier.getUsername(), userIdentifier.getUuid()).getOrDefault(false);
return backing.saveUUIDData(userIdentifier.getUsername(), userIdentifier.getUuid()).getOrDefault(false);
}
};
@ -93,7 +85,6 @@ public class BufferedOutputDatastore implements Datastore, Runnable {
}
public void flush(long flushTime) {
logOutputBuffer.flush(flushTime);
userOutputBuffer.flush(flushTime);
groupOutputBuffer.flush(flushTime);
trackOutputBuffer.flush(flushTime);
@ -104,134 +95,38 @@ public class BufferedOutputDatastore implements Datastore, Runnable {
return backing;
}
@Override
public LPFuture<Void> init() {
return backing.init();
}
@Override
public LPFuture<Void> shutdown() {
forceFlush();
return backing.shutdown();
}
@Override
public LPFuture<Boolean> logAction(LogEntry entry) {
return logOutputBuffer.enqueue(entry);
}
@Override
public LPFuture<Log> getLog() {
return backing.getLog();
}
@Override
public LPFuture<Boolean> loadUser(UUID uuid, String username) {
return backing.loadUser(uuid, username);
}
@Override
public LPFuture<Boolean> saveUser(User user) {
return userOutputBuffer.enqueue(user);
}
@Override
public LPFuture<Boolean> cleanupUsers() {
return backing.cleanupUsers();
}
@Override
public LPFuture<Set<UUID>> getUniqueUsers() {
return backing.getUniqueUsers();
}
@Override
public LPFuture<Boolean> createAndLoadGroup(String name) {
return backing.createAndLoadGroup(name);
}
@Override
public LPFuture<Boolean> loadGroup(String name) {
return backing.loadGroup(name);
}
@Override
public LPFuture<Boolean> loadAllGroups() {
return backing.loadAllGroups();
}
@Override
public LPFuture<Boolean> saveGroup(Group group) {
return groupOutputBuffer.enqueue(group);
}
@Override
public LPFuture<Boolean> deleteGroup(Group group) {
return backing.deleteGroup(group);
}
@Override
public LPFuture<Boolean> createAndLoadTrack(String name) {
return backing.createAndLoadTrack(name);
}
@Override
public LPFuture<Boolean> loadTrack(String name) {
return backing.loadTrack(name);
}
@Override
public LPFuture<Boolean> loadAllTracks() {
return backing.loadAllTracks();
}
@Override
public LPFuture<Boolean> saveTrack(Track track) {
return trackOutputBuffer.enqueue(track);
}
@Override
public LPFuture<Boolean> deleteTrack(Track track) {
return backing.deleteTrack(track);
}
@Override
public LPFuture<Boolean> saveUUIDData(String username, UUID uuid) {
return uuidDataOutputBuffer.enqueue(UserIdentifier.of(uuid, username));
}
@Override
public LPFuture<UUID> getUUID(String username) {
return backing.getUUID(username);
}
@Override
public LPFuture<String> getName(UUID uuid) {
return backing.getName(uuid);
}
@Override
public String getName() {
return backing.getName();
}
@Override
public boolean isAcceptingLogins() {
return backing.isAcceptingLogins();
}
@Override
public void setAcceptingLogins(boolean acceptingLogins) {
backing.setAcceptingLogins(acceptingLogins);
}
@Override
public void doAsync(Runnable r) {
backing.doAsync(r);
}
@Override
public void doSync(Runnable r) {
backing.doSync(r);
private interface Exclude {
Datastore force();
LPFuture<Void> shutdown();
LPFuture<Boolean> saveUser(User user);
LPFuture<Boolean> saveGroup(Group group);
LPFuture<Boolean> saveTrack(Track track);
LPFuture<Boolean> saveUUIDData(String username, UUID uuid);
}
}

View File

@ -84,8 +84,8 @@ public class StorageFactory {
private static Datastore fromString(String storageMethod, LuckPermsPlugin plugin) {
switch (storageMethod) {
case "mysql":
BufferedOutputDatastore bod = BufferedOutputDatastore.wrap(AbstractDatastore.wrap(new MySQLBacking(plugin, plugin.getConfiguration().getDatabaseValues())), 5000L);
plugin.doAsyncRepeating(bod, 20L);
BufferedOutputDatastore bod = BufferedOutputDatastore.wrap(AbstractDatastore.wrap(new MySQLBacking(plugin, plugin.getConfiguration().getDatabaseValues())), 3000L);
plugin.doAsyncRepeating(bod, 10L);
return bod;
case "sqlite":
return AbstractDatastore.wrap(new SQLiteBacking(plugin, new File(plugin.getDataFolder(), "luckperms.sqlite")));

View File

@ -34,6 +34,8 @@ import me.lucko.luckperms.common.utils.LPFuture;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.Phaser;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
/**
* A Datastore wrapping that ensures all tasks are completed before {@link Datastore#shutdown()} is called.
@ -84,8 +86,12 @@ public class TolerantDatastore implements Datastore {
@Override
public LPFuture<Void> shutdown() {
phaser.register(); // Register self
phaser.arriveAndAwaitAdvance(); // Wait for other threads to finish.
// Wait for other threads to finish.
try {
phaser.awaitAdvanceInterruptibly(phaser.getPhase(), 5, TimeUnit.SECONDS);
} catch (InterruptedException | TimeoutException e) {
e.printStackTrace();
}
return backing.shutdown();
}

View File

@ -140,7 +140,7 @@ public class JSONBacking extends FlatfileBacking {
}, false);
} finally {
user.getIoLock().unlock();
user.refreshPermissions();
user.getRefreshBuffer().requestDirectly();
}
}

View File

@ -178,7 +178,7 @@ public class MongoDBBacking extends AbstractBacking {
}, false);
} finally {
user.getIoLock().unlock();
user.refreshPermissions();
user.getRefreshBuffer().requestDirectly();
}
}

View File

@ -184,7 +184,7 @@ abstract class SQLBacking extends AbstractBacking {
);
} finally {
user.getIoLock().unlock();
user.refreshPermissions();
user.getRefreshBuffer().requestDirectly();
}
}

View File

@ -126,7 +126,7 @@ public class YAMLBacking extends FlatfileBacking {
}, false);
} finally {
user.getIoLock().unlock();
user.refreshPermissions();
user.getRefreshBuffer().requestDirectly();
}
}

View File

@ -31,6 +31,7 @@ import me.lucko.luckperms.common.LuckPermsPlugin;
import me.lucko.luckperms.common.api.internal.UserLink;
import me.lucko.luckperms.common.caching.UserData;
import me.lucko.luckperms.common.core.PermissionHolder;
import me.lucko.luckperms.common.utils.BufferedRequest;
import me.lucko.luckperms.common.utils.Identifiable;
import java.util.UUID;
@ -62,6 +63,15 @@ public class User extends PermissionHolder implements Identifiable<UserIdentifie
@Getter
private UserData userData = null;
@Getter
private BufferedRequest<Void> refreshBuffer = new BufferedRequest<Void>(1000L, r -> getPlugin().doAsync(r)) {
@Override
protected Void perform() {
refreshPermissions();
return null;
}
};
protected User(UUID uuid, LuckPermsPlugin plugin) {
super(uuid.toString(), plugin);
this.uuid = uuid;
@ -111,7 +121,7 @@ public class User extends PermissionHolder implements Identifiable<UserIdentifie
* Refresh and re-assign the users permissions
* Blocking call.
*/
public synchronized void refreshPermissions() {
private synchronized void refreshPermissions() {
if (userData == null) {
return;
}

View File

@ -135,9 +135,9 @@ public class UserManager extends AbstractManager<UserIdentifier, User> {
plugin.doAsync(() -> {
for (UUID uuid : players) {
UUID internal = plugin.getUuidCache().getUUID(uuid);
plugin.getDatastore().loadUser(internal, "null");
plugin.getDatastore().loadUser(internal, "null").getOrDefault(false);
User user = get(internal);
user.refreshPermissions();
user.getRefreshBuffer().request();
}
});
});

View File

@ -41,14 +41,14 @@ public class AbstractListener {
final UuidCache cache = plugin.getUuidCache();
if (!cache.isOnlineMode()) {
UUID uuid = plugin.getDatastore().getUUID(username).getOrDefault(null);
UUID uuid = plugin.getDatastore().force().getUUID(username).getOrDefault(null);
if (uuid != null) {
cache.addToCache(u, uuid);
} else {
// No previous data for this player
plugin.getApiProvider().fireEventAsync(new UserFirstLoginEvent(u, username));
cache.addToCache(u, u);
plugin.getDatastore().saveUUIDData(username, u, Callback.empty());
plugin.getDatastore().force().saveUUIDData(username, u, Callback.empty());
}
} else {
UUID uuid = plugin.getDatastore().getUUID(username).getOrDefault(null);
@ -57,10 +57,10 @@ public class AbstractListener {
}
// Online mode, no cache needed. This is just for name -> uuid lookup.
plugin.getDatastore().saveUUIDData(username, u, Callback.empty());
plugin.getDatastore().force().saveUUIDData(username, u, Callback.empty());
}
plugin.getDatastore().loadUser(cache.getUUID(u), username);
plugin.getDatastore().force().loadUser(cache.getUUID(u), username).getOrDefault(false);
User user = plugin.getUserManager().get(cache.getUUID(u));
if (user == null) {
plugin.getLog().warn("Failed to load user: " + username);
@ -75,7 +75,7 @@ public class AbstractListener {
// If they were given a default, persist the new assignments back to the storage.
if (save) {
plugin.getDatastore().saveUser(user);
plugin.getDatastore().force().saveUser(user).getOrDefault(false);
}
user.setupData(false); // Pretty nasty calculation call. Sets up the caching system so data is ready when the user joins.
@ -103,7 +103,7 @@ public class AbstractListener {
protected void refreshPlayer(UUID uuid) {
final User user = plugin.getUserManager().get(plugin.getUuidCache().getUUID(uuid));
if (user != null) {
user.refreshPermissions();
user.getRefreshBuffer().requestDirectly();
}
}
}

View File

@ -27,7 +27,6 @@ import lombok.RequiredArgsConstructor;
import me.lucko.luckperms.common.storage.AbstractFuture;
import java.lang.ref.WeakReference;
import java.util.concurrent.Future;
import java.util.concurrent.locks.ReentrantLock;
import java.util.function.Consumer;
import java.util.function.Supplier;
@ -42,7 +41,7 @@ public abstract class BufferedRequest<T> {
@Getter
private ReentrantLock lock = new ReentrantLock();
public Future<T> request() {
public LPFuture<T> request() {
lock.lock();
try {
if (processor != null) {
@ -62,6 +61,10 @@ public abstract class BufferedRequest<T> {
}
}
public T requestDirectly() {
return perform();
}
protected abstract T perform();
@ -109,11 +112,11 @@ public abstract class BufferedRequest<T> {
future.complete(result);
}
public Future<R> get() {
public LPFuture<R> get() {
return future;
}
public Future<R> getAndExtend() {
public LPFuture<R> getAndExtend() {
lock.lock();
try {
executionTime = System.currentTimeMillis() + delayMillis;

View File

@ -46,6 +46,7 @@ import me.lucko.luckperms.common.storage.Datastore;
import me.lucko.luckperms.common.storage.StorageFactory;
import me.lucko.luckperms.common.tracks.TrackManager;
import me.lucko.luckperms.common.users.UserManager;
import me.lucko.luckperms.common.utils.BufferedRequest;
import me.lucko.luckperms.common.utils.LocaleManager;
import me.lucko.luckperms.common.utils.LogFactory;
import me.lucko.luckperms.sponge.contexts.WorldCalculator;
@ -106,6 +107,7 @@ public class LPSpongePlugin implements LuckPermsPlugin {
private LocaleManager localeManager;
private ContextManager<Subject> contextManager;
private CalculatorFactory calculatorFactory;
private BufferedRequest<Void> updateTaskBuffer;
@Listener
public void onEnable(GamePreInitializationEvent event) {
@ -157,13 +159,22 @@ public class LPSpongePlugin implements LuckPermsPlugin {
ApiHandler.registerProvider(apiProvider);
Sponge.getServiceManager().setProvider(this, LuckPermsApi.class, apiProvider);
final LPSpongePlugin i = this;
updateTaskBuffer = new BufferedRequest<Void>(6000L, this::doAsync) {
@Override
protected Void perform() {
scheduler.createTaskBuilder().async().execute(new UpdateTask(i)).submit(i);
return null;
}
};
int mins = getConfiguration().getSyncTime();
if (mins > 0) {
scheduler.createTaskBuilder().async().interval(mins, TimeUnit.MINUTES).execute(new UpdateTask(this))
.submit(LPSpongePlugin.this);
} else {
// Update online users
runUpdateTask();
updateTaskBuffer.request();
}
scheduler.createTaskBuilder().intervalTicks(1L).execute(SpongeSenderFactory.get(this)).submit(this);
@ -292,11 +303,6 @@ public class LPSpongePlugin implements LuckPermsPlugin {
return game.getPluginManager().isLoaded(name);
}
@Override
public void runUpdateTask() {
scheduler.createTaskBuilder().async().execute(new UpdateTask(this)).submit(this);
}
@Override
public void doAsync(Runnable r) {
scheduler.createTaskBuilder().async().execute(r).submit(this);

View File

@ -52,16 +52,12 @@ public class LuckPermsSubjectData implements SubjectData {
private final PermissionHolder holder;
private void objectSave(PermissionHolder t) {
service.getPlugin().doAsync(() -> {
if (t instanceof User) {
((User) t).refreshPermissions();
service.getPlugin().getDatastore().saveUser(((User) t));
}
if (t instanceof Group) {
service.getPlugin().getDatastore().saveGroup(((Group) t));
service.getPlugin().runUpdateTask();
}
});
if (t instanceof User) {
service.getPlugin().getDatastore().saveUser(((User) t), b -> ((User) t).getRefreshBuffer().request());
}
if (t instanceof Group) {
service.getPlugin().getDatastore().saveGroup(((Group) t), b -> service.getPlugin().getUpdateTaskBuffer().request());
}
}
@Override