Remove storage buffers
This commit is contained in:
parent
7d089cb5f0
commit
2e136666be
@ -211,13 +211,18 @@ public class MigrationZPermissions extends SubCommand<Object> {
|
||||
|
||||
for (EntityMetadata metadata : entity.getMetadata()) {
|
||||
String key = metadata.getName().toLowerCase();
|
||||
if (key.isEmpty() || metadata.getStringValue().isEmpty()) continue;
|
||||
Object value = metadata.getValue();
|
||||
|
||||
if (key.isEmpty() || value == null) continue;
|
||||
|
||||
String valueString = value.toString();
|
||||
if (valueString.isEmpty()) continue;
|
||||
|
||||
if (key.equals(NodeFactory.PREFIX_KEY) || key.equals(NodeFactory.SUFFIX_KEY)) {
|
||||
ChatMetaType type = ChatMetaType.valueOf(key.toUpperCase());
|
||||
holder.setPermission(NodeFactory.buildChatMetaNode(type, weight, metadata.getStringValue()).build());
|
||||
holder.setPermission(NodeFactory.buildChatMetaNode(type, weight, valueString).build());
|
||||
} else {
|
||||
holder.setPermission(NodeFactory.buildMetaNode(key, metadata.getStringValue()).build());
|
||||
holder.setPermission(NodeFactory.buildMetaNode(key, valueString).build());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -60,7 +60,7 @@ public class ApiGroupManager extends ApiAbstractManager<Group, me.lucko.luckperm
|
||||
@Override
|
||||
public CompletableFuture<me.lucko.luckperms.api.Group> createAndLoadGroup(@Nonnull String name) {
|
||||
name = ApiUtils.checkName(Objects.requireNonNull(name, "name"));
|
||||
return this.plugin.getStorage().noBuffer().createAndLoadGroup(name, CreationCause.API)
|
||||
return this.plugin.getStorage().createAndLoadGroup(name, CreationCause.API)
|
||||
.thenApply(this::getDelegateFor);
|
||||
}
|
||||
|
||||
@ -68,14 +68,14 @@ public class ApiGroupManager extends ApiAbstractManager<Group, me.lucko.luckperm
|
||||
@Override
|
||||
public CompletableFuture<Optional<me.lucko.luckperms.api.Group>> loadGroup(@Nonnull String name) {
|
||||
name = ApiUtils.checkName(Objects.requireNonNull(name, "name"));
|
||||
return this.plugin.getStorage().noBuffer().loadGroup(name).thenApply(opt -> opt.map(this::getDelegateFor));
|
||||
return this.plugin.getStorage().loadGroup(name).thenApply(opt -> opt.map(this::getDelegateFor));
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public CompletableFuture<Void> saveGroup(@Nonnull me.lucko.luckperms.api.Group group) {
|
||||
Objects.requireNonNull(group, "group");
|
||||
return this.plugin.getStorage().noBuffer().saveGroup(ApiGroup.cast(group));
|
||||
return this.plugin.getStorage().saveGroup(ApiGroup.cast(group));
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@ -85,13 +85,13 @@ public class ApiGroupManager extends ApiAbstractManager<Group, me.lucko.luckperm
|
||||
if (group.getName().equalsIgnoreCase(NodeFactory.DEFAULT_GROUP_NAME)) {
|
||||
throw new IllegalArgumentException("Cannot delete the default group.");
|
||||
}
|
||||
return this.plugin.getStorage().noBuffer().deleteGroup(ApiGroup.cast(group), DeletionCause.API);
|
||||
return this.plugin.getStorage().deleteGroup(ApiGroup.cast(group), DeletionCause.API);
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public CompletableFuture<Void> loadAllGroups() {
|
||||
return this.plugin.getStorage().noBuffer().loadAllGroups();
|
||||
return this.plugin.getStorage().loadAllGroups();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -59,7 +59,7 @@ public class ApiTrackManager extends ApiAbstractManager<Track, me.lucko.luckperm
|
||||
@Override
|
||||
public CompletableFuture<me.lucko.luckperms.api.Track> createAndLoadTrack(@Nonnull String name) {
|
||||
name = ApiUtils.checkName(Objects.requireNonNull(name, "name"));
|
||||
return this.plugin.getStorage().noBuffer().createAndLoadTrack(name, CreationCause.API)
|
||||
return this.plugin.getStorage().createAndLoadTrack(name, CreationCause.API)
|
||||
.thenApply(this::getDelegateFor);
|
||||
}
|
||||
|
||||
@ -67,27 +67,27 @@ public class ApiTrackManager extends ApiAbstractManager<Track, me.lucko.luckperm
|
||||
@Override
|
||||
public CompletableFuture<Optional<me.lucko.luckperms.api.Track>> loadTrack(@Nonnull String name) {
|
||||
name = ApiUtils.checkName(Objects.requireNonNull(name, "name"));
|
||||
return this.plugin.getStorage().noBuffer().loadTrack(name).thenApply(opt -> opt.map(this::getDelegateFor));
|
||||
return this.plugin.getStorage().loadTrack(name).thenApply(opt -> opt.map(this::getDelegateFor));
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public CompletableFuture<Void> saveTrack(@Nonnull me.lucko.luckperms.api.Track track) {
|
||||
Objects.requireNonNull(track, "track");
|
||||
return this.plugin.getStorage().noBuffer().saveTrack(ApiTrack.cast(track));
|
||||
return this.plugin.getStorage().saveTrack(ApiTrack.cast(track));
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public CompletableFuture<Void> deleteTrack(@Nonnull me.lucko.luckperms.api.Track track) {
|
||||
Objects.requireNonNull(track, "track");
|
||||
return this.plugin.getStorage().noBuffer().deleteTrack(ApiTrack.cast(track), DeletionCause.API);
|
||||
return this.plugin.getStorage().deleteTrack(ApiTrack.cast(track), DeletionCause.API);
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public CompletableFuture<Void> loadAllTracks() {
|
||||
return this.plugin.getStorage().noBuffer().loadAllTracks();
|
||||
return this.plugin.getStorage().loadAllTracks();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -64,7 +64,7 @@ public class ApiUserManager extends ApiAbstractManager<User, me.lucko.luckperms.
|
||||
this.plugin.getUserManager().getHouseKeeper().registerApiUsage(uuid);
|
||||
}
|
||||
|
||||
return this.plugin.getStorage().noBuffer().loadUser(uuid, username)
|
||||
return this.plugin.getStorage().loadUser(uuid, username)
|
||||
.thenApply(this::getDelegateFor);
|
||||
}
|
||||
|
||||
@ -72,7 +72,7 @@ public class ApiUserManager extends ApiAbstractManager<User, me.lucko.luckperms.
|
||||
@Override
|
||||
public CompletableFuture<Void> saveUser(@Nonnull me.lucko.luckperms.api.User user) {
|
||||
Objects.requireNonNull(user, "user");
|
||||
return this.plugin.getStorage().noBuffer().saveUser(ApiUser.cast(user));
|
||||
return this.plugin.getStorage().saveUser(ApiUser.cast(user));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -52,7 +52,7 @@ public class ApiActionLogger implements ActionLogger {
|
||||
@Nonnull
|
||||
@Override
|
||||
public CompletableFuture<Log> getLog() {
|
||||
return this.plugin.getStorage().noBuffer().getLog().thenApply(ApiLog::new);
|
||||
return this.plugin.getStorage().getLog().thenApply(ApiLog::new);
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@ -64,7 +64,7 @@ public class ApiActionLogger implements ActionLogger {
|
||||
@Nonnull
|
||||
@Override
|
||||
public CompletableFuture<Void> submitToStorage(@Nonnull LogEntry entry) {
|
||||
return this.plugin.getStorage().noBuffer().logAction(entry);
|
||||
return this.plugin.getStorage().logAction(entry);
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
|
@ -103,7 +103,7 @@ public class ApiStorage implements me.lucko.luckperms.api.Storage {
|
||||
@Override
|
||||
public CompletableFuture<Boolean> logAction(@Nonnull LogEntry entry) {
|
||||
Objects.requireNonNull(entry, "entry");
|
||||
return this.handle.noBuffer().logAction(entry)
|
||||
return this.handle.logAction(entry)
|
||||
.thenApply(r -> true)
|
||||
.exceptionally(consumeExceptionToFalse());
|
||||
}
|
||||
@ -111,7 +111,7 @@ public class ApiStorage implements me.lucko.luckperms.api.Storage {
|
||||
@Nonnull
|
||||
@Override
|
||||
public CompletableFuture<Log> getLog() {
|
||||
return this.handle.noBuffer().getLog().<Log>thenApply(ApiLog::new).exceptionally(consumeExceptionToNull());
|
||||
return this.handle.getLog().<Log>thenApply(ApiLog::new).exceptionally(consumeExceptionToNull());
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@ -124,7 +124,7 @@ public class ApiStorage implements me.lucko.luckperms.api.Storage {
|
||||
this.plugin.getUserManager().getHouseKeeper().registerApiUsage(uuid);
|
||||
}
|
||||
|
||||
return this.handle.noBuffer().loadUser(uuid, username)
|
||||
return this.handle.loadUser(uuid, username)
|
||||
.thenApply(r -> true)
|
||||
.exceptionally(consumeExceptionToFalse());
|
||||
}
|
||||
@ -133,7 +133,7 @@ public class ApiStorage implements me.lucko.luckperms.api.Storage {
|
||||
@Override
|
||||
public CompletableFuture<Boolean> saveUser(@Nonnull User user) {
|
||||
Objects.requireNonNull(user, "user");
|
||||
return this.handle.noBuffer().saveUser(ApiUser.cast(user))
|
||||
return this.handle.saveUser(ApiUser.cast(user))
|
||||
.thenApply(r -> true)
|
||||
.exceptionally(consumeExceptionToFalse());
|
||||
}
|
||||
@ -141,21 +141,21 @@ public class ApiStorage implements me.lucko.luckperms.api.Storage {
|
||||
@Nonnull
|
||||
@Override
|
||||
public CompletableFuture<Set<UUID>> getUniqueUsers() {
|
||||
return this.handle.noBuffer().getUniqueUsers().exceptionally(consumeExceptionToNull());
|
||||
return this.handle.getUniqueUsers().exceptionally(consumeExceptionToNull());
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public CompletableFuture<List<HeldPermission<UUID>>> getUsersWithPermission(@Nonnull String permission) {
|
||||
Objects.requireNonNull(permission, "permission");
|
||||
return this.handle.noBuffer().getUsersWithPermission(permission).exceptionally(consumeExceptionToNull());
|
||||
return this.handle.getUsersWithPermission(permission).exceptionally(consumeExceptionToNull());
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public CompletableFuture<Boolean> createAndLoadGroup(@Nonnull String name) {
|
||||
Objects.requireNonNull(name, "name");
|
||||
return this.handle.noBuffer().createAndLoadGroup(checkName(name), CreationCause.API)
|
||||
return this.handle.createAndLoadGroup(checkName(name), CreationCause.API)
|
||||
.thenApply(r -> true)
|
||||
.exceptionally(consumeExceptionToFalse());
|
||||
}
|
||||
@ -164,7 +164,7 @@ public class ApiStorage implements me.lucko.luckperms.api.Storage {
|
||||
@Override
|
||||
public CompletableFuture<Boolean> loadGroup(@Nonnull String name) {
|
||||
Objects.requireNonNull(name, "name");
|
||||
return this.handle.noBuffer().loadGroup(checkName(name))
|
||||
return this.handle.loadGroup(checkName(name))
|
||||
.thenApply(Optional::isPresent)
|
||||
.exceptionally(consumeExceptionToFalse());
|
||||
}
|
||||
@ -172,7 +172,7 @@ public class ApiStorage implements me.lucko.luckperms.api.Storage {
|
||||
@Nonnull
|
||||
@Override
|
||||
public CompletableFuture<Boolean> loadAllGroups() {
|
||||
return this.handle.noBuffer().loadAllGroups()
|
||||
return this.handle.loadAllGroups()
|
||||
.thenApply(r -> true)
|
||||
.exceptionally(consumeExceptionToFalse());
|
||||
}
|
||||
@ -181,7 +181,7 @@ public class ApiStorage implements me.lucko.luckperms.api.Storage {
|
||||
@Override
|
||||
public CompletableFuture<Boolean> saveGroup(@Nonnull Group group) {
|
||||
Objects.requireNonNull(group, "group");
|
||||
return this.handle.noBuffer().saveGroup(ApiGroup.cast(group))
|
||||
return this.handle.saveGroup(ApiGroup.cast(group))
|
||||
.thenApply(r -> true)
|
||||
.exceptionally(consumeExceptionToFalse());
|
||||
}
|
||||
@ -193,7 +193,7 @@ public class ApiStorage implements me.lucko.luckperms.api.Storage {
|
||||
if (group.getName().equalsIgnoreCase(NodeFactory.DEFAULT_GROUP_NAME)) {
|
||||
throw new IllegalArgumentException("Cannot delete the default group.");
|
||||
}
|
||||
return this.handle.noBuffer().deleteGroup(ApiGroup.cast(group), DeletionCause.API)
|
||||
return this.handle.deleteGroup(ApiGroup.cast(group), DeletionCause.API)
|
||||
.thenApply(r -> true)
|
||||
.exceptionally(consumeExceptionToFalse());
|
||||
}
|
||||
@ -202,14 +202,14 @@ public class ApiStorage implements me.lucko.luckperms.api.Storage {
|
||||
@Override
|
||||
public CompletableFuture<List<HeldPermission<String>>> getGroupsWithPermission(@Nonnull String permission) {
|
||||
Objects.requireNonNull(permission, "permission");
|
||||
return this.handle.noBuffer().getGroupsWithPermission(permission).exceptionally(consumeExceptionToNull());
|
||||
return this.handle.getGroupsWithPermission(permission).exceptionally(consumeExceptionToNull());
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public CompletableFuture<Boolean> createAndLoadTrack(@Nonnull String name) {
|
||||
Objects.requireNonNull(name, "name");
|
||||
return this.handle.noBuffer().createAndLoadTrack(checkName(name), CreationCause.API)
|
||||
return this.handle.createAndLoadTrack(checkName(name), CreationCause.API)
|
||||
.thenApply(r -> true)
|
||||
.exceptionally(consumeExceptionToFalse());
|
||||
}
|
||||
@ -218,7 +218,7 @@ public class ApiStorage implements me.lucko.luckperms.api.Storage {
|
||||
@Override
|
||||
public CompletableFuture<Boolean> loadTrack(@Nonnull String name) {
|
||||
Objects.requireNonNull(name, "name");
|
||||
return this.handle.noBuffer().loadTrack(checkName(name))
|
||||
return this.handle.loadTrack(checkName(name))
|
||||
.thenApply(Optional::isPresent)
|
||||
.exceptionally(consumeExceptionToFalse());
|
||||
}
|
||||
@ -226,7 +226,7 @@ public class ApiStorage implements me.lucko.luckperms.api.Storage {
|
||||
@Nonnull
|
||||
@Override
|
||||
public CompletableFuture<Boolean> loadAllTracks() {
|
||||
return this.handle.noBuffer().loadAllTracks()
|
||||
return this.handle.loadAllTracks()
|
||||
.thenApply(r -> true)
|
||||
.exceptionally(consumeExceptionToFalse());
|
||||
}
|
||||
@ -235,7 +235,7 @@ public class ApiStorage implements me.lucko.luckperms.api.Storage {
|
||||
@Override
|
||||
public CompletableFuture<Boolean> saveTrack(@Nonnull Track track) {
|
||||
Objects.requireNonNull(track, "track");
|
||||
return this.handle.noBuffer().saveTrack(ApiTrack.cast(track))
|
||||
return this.handle.saveTrack(ApiTrack.cast(track))
|
||||
.thenApply(r -> true)
|
||||
.exceptionally(consumeExceptionToFalse());
|
||||
}
|
||||
@ -244,7 +244,7 @@ public class ApiStorage implements me.lucko.luckperms.api.Storage {
|
||||
@Override
|
||||
public CompletableFuture<Boolean> deleteTrack(@Nonnull Track track) {
|
||||
Objects.requireNonNull(track, "track");
|
||||
return this.handle.noBuffer().deleteTrack(ApiTrack.cast(track), DeletionCause.API)
|
||||
return this.handle.deleteTrack(ApiTrack.cast(track), DeletionCause.API)
|
||||
.thenApply(r -> true)
|
||||
.exceptionally(consumeExceptionToFalse());
|
||||
}
|
||||
@ -254,7 +254,7 @@ public class ApiStorage implements me.lucko.luckperms.api.Storage {
|
||||
public CompletableFuture<Boolean> saveUUIDData(@Nonnull String username, @Nonnull UUID uuid) {
|
||||
Objects.requireNonNull(username, "username");
|
||||
Objects.requireNonNull(uuid, "uuid");
|
||||
return this.handle.noBuffer().savePlayerData(uuid, checkUsername(username))
|
||||
return this.handle.savePlayerData(uuid, checkUsername(username))
|
||||
.thenApply(r -> true)
|
||||
.exceptionally(consumeExceptionToFalse());
|
||||
}
|
||||
@ -263,13 +263,13 @@ public class ApiStorage implements me.lucko.luckperms.api.Storage {
|
||||
@Override
|
||||
public CompletableFuture<UUID> getUUID(@Nonnull String username) {
|
||||
Objects.requireNonNull(username, "username");
|
||||
return this.handle.noBuffer().getPlayerUuid(checkUsername(username));
|
||||
return this.handle.getPlayerUuid(checkUsername(username));
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public CompletableFuture<String> getName(@Nonnull UUID uuid) {
|
||||
Objects.requireNonNull(uuid, "uuid");
|
||||
return this.handle.noBuffer().getPlayerName(uuid);
|
||||
return this.handle.getPlayerName(uuid);
|
||||
}
|
||||
}
|
||||
|
@ -1,164 +0,0 @@
|
||||
/*
|
||||
* This file is part of LuckPerms, licensed under the MIT License.
|
||||
*
|
||||
* Copyright (c) lucko (Luck) <luck@lucko.me>
|
||||
* Copyright (c) contributors
|
||||
*
|
||||
* 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.buffers;
|
||||
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.ListIterator;
|
||||
import java.util.Objects;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
import java.util.function.Function;
|
||||
|
||||
/**
|
||||
* Thread-safe buffer utility. Holds a buffer of objects to be processed after they've been waiting in the buffer
|
||||
* for a given time. If the same object is pushed to the buffer again in that time, its wait time is reset.
|
||||
*
|
||||
* @param <T> the type of objects in the buffer
|
||||
* @param <R> the type of result produced by the final process
|
||||
*/
|
||||
public class Buffer<T, R> implements Runnable {
|
||||
private static final long DEFAULT_FLUSH_TIME = 1000; // 1 second
|
||||
|
||||
public static <T, R> Buffer<T, R> of(Function<T, R> dequeueFunc) {
|
||||
return new Buffer<>(dequeueFunc);
|
||||
}
|
||||
|
||||
private final ReentrantLock lock = new ReentrantLock();
|
||||
private final List<BufferedObject<T, R>> buffer = new LinkedList<>();
|
||||
private final Function<T, R> dequeueFunc;
|
||||
|
||||
private Buffer(Function<T, R> dequeueFunc) {
|
||||
this.dequeueFunc = dequeueFunc;
|
||||
}
|
||||
|
||||
public CompletableFuture<R> enqueue(T object) {
|
||||
Objects.requireNonNull(object, "object");
|
||||
|
||||
this.lock.lock();
|
||||
try {
|
||||
ListIterator<BufferedObject<T, R>> it = this.buffer.listIterator();
|
||||
|
||||
BufferedObject<T, R> o = null;
|
||||
|
||||
while (it.hasNext()) {
|
||||
BufferedObject<T, R> obj = it.next();
|
||||
|
||||
if (obj.getObject().equals(object)) {
|
||||
o = obj;
|
||||
it.remove();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (o == null) {
|
||||
o = new BufferedObject<>(System.currentTimeMillis(), object, new CompletableFuture<R>());
|
||||
} else {
|
||||
o.setBufferTime(System.currentTimeMillis());
|
||||
}
|
||||
|
||||
this.buffer.add(o);
|
||||
return o.getFuture();
|
||||
} finally {
|
||||
this.lock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
protected R dequeue(T t) {
|
||||
return this.dequeueFunc.apply(t);
|
||||
}
|
||||
|
||||
public void flush(long flushTime) {
|
||||
long time = System.currentTimeMillis();
|
||||
|
||||
this.lock.lock();
|
||||
try {
|
||||
ListIterator<BufferedObject<T, R>> it = this.buffer.listIterator(this.buffer.size());
|
||||
|
||||
while (it.hasPrevious()) {
|
||||
BufferedObject<T, R> obj = it.previous();
|
||||
long bufferedTime = time - obj.getBufferTime();
|
||||
|
||||
if (bufferedTime > flushTime) {
|
||||
|
||||
// Flush
|
||||
R r = dequeue(obj.getObject());
|
||||
obj.getFuture().complete(r);
|
||||
it.remove();
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
this.lock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
flush(DEFAULT_FLUSH_TIME);
|
||||
}
|
||||
|
||||
private static final class BufferedObject<T, R> {
|
||||
|
||||
private long bufferTime;
|
||||
private final T object;
|
||||
private final CompletableFuture<R> future;
|
||||
|
||||
public BufferedObject(long bufferTime, T object, CompletableFuture<R> future) {
|
||||
this.bufferTime = bufferTime;
|
||||
this.object = object;
|
||||
this.future = future;
|
||||
}
|
||||
|
||||
public long getBufferTime() {
|
||||
return this.bufferTime;
|
||||
}
|
||||
|
||||
public void setBufferTime(long bufferTime) {
|
||||
this.bufferTime = bufferTime;
|
||||
}
|
||||
|
||||
public T getObject() {
|
||||
return this.object;
|
||||
}
|
||||
|
||||
public CompletableFuture<R> getFuture() {
|
||||
return this.future;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (o == this) return true;
|
||||
if (!(o instanceof Buffer.BufferedObject)) return false;
|
||||
final BufferedObject that = (BufferedObject) o;
|
||||
return Objects.equals(this.getObject(), that.getObject());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hashCode(this.object);
|
||||
}
|
||||
}
|
||||
}
|
@ -101,7 +101,7 @@ public final class StorageAssistant {
|
||||
}
|
||||
|
||||
try {
|
||||
plugin.getStorage().noBuffer().saveUser(user).get();
|
||||
plugin.getStorage().saveUser(user).get();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
Message.USER_SAVE_ERROR.send(sender, user.getFriendlyName());
|
||||
@ -125,7 +125,7 @@ public final class StorageAssistant {
|
||||
}
|
||||
|
||||
try {
|
||||
plugin.getStorage().noBuffer().saveGroup(group).get();
|
||||
plugin.getStorage().saveGroup(group).get();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
Message.GROUP_SAVE_ERROR.send(sender, group.getFriendlyName());
|
||||
@ -149,7 +149,7 @@ public final class StorageAssistant {
|
||||
}
|
||||
|
||||
try {
|
||||
plugin.getStorage().noBuffer().saveTrack(track).get();
|
||||
plugin.getStorage().saveTrack(track).get();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
Message.TRACK_SAVE_ERROR.send(sender, track.getName());
|
||||
|
@ -77,7 +77,7 @@ public class LogNotify extends SubCommand<Log> {
|
||||
user.removeIf(n -> n.getPermission().equalsIgnoreCase("luckperms.log.notify.ignoring"));
|
||||
}
|
||||
|
||||
plugin.getStorage().noBuffer().saveUser(user).join();
|
||||
plugin.getStorage().saveUser(user).join();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -73,7 +73,7 @@ public abstract class AbstractConnectionListener implements ConnectionListener {
|
||||
this.plugin.getLogger().warn("This is usually because the server is not authenticating correctly. If you're using BungeeCord, please ensure that IP-Forwarding is setup correctly!");
|
||||
}
|
||||
|
||||
User user = this.plugin.getStorage().noBuffer().loadUser(u, username).join();
|
||||
User user = this.plugin.getStorage().loadUser(u, username).join();
|
||||
if (user == null) {
|
||||
throw new NullPointerException("User is null");
|
||||
} else {
|
||||
@ -87,7 +87,7 @@ public abstract class AbstractConnectionListener implements ConnectionListener {
|
||||
|
||||
// If they were given a default, persist the new assignments back to the storage.
|
||||
if (save) {
|
||||
this.plugin.getStorage().noBuffer().saveUser(user).join();
|
||||
this.plugin.getStorage().saveUser(user).join();
|
||||
}
|
||||
|
||||
// Does some minimum pre-calculations to (maybe) speed things up later.
|
||||
|
@ -40,7 +40,6 @@ import me.lucko.luckperms.common.model.Track;
|
||||
import me.lucko.luckperms.common.model.User;
|
||||
import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
|
||||
import me.lucko.luckperms.common.storage.dao.AbstractDao;
|
||||
import me.lucko.luckperms.common.storage.wrappings.BufferedOutputStorage;
|
||||
import me.lucko.luckperms.common.storage.wrappings.PhasedStorage;
|
||||
|
||||
import java.util.List;
|
||||
@ -60,11 +59,7 @@ public class AbstractStorage implements Storage {
|
||||
// make a base implementation
|
||||
Storage base = new AbstractStorage(plugin, backing);
|
||||
// wrap with a phaser
|
||||
PhasedStorage phased = PhasedStorage.wrap(base);
|
||||
// wrap with a buffer
|
||||
BufferedOutputStorage buffered = BufferedOutputStorage.wrap(phased, 250L);
|
||||
plugin.getBootstrap().getScheduler().asyncRepeating(buffered.buffer(), 2L);
|
||||
return buffered;
|
||||
return PhasedStorage.wrap(base);
|
||||
}
|
||||
|
||||
private final LuckPermsPlugin plugin;
|
||||
|
@ -1,140 +0,0 @@
|
||||
/*
|
||||
* This file is part of LuckPerms, licensed under the MIT License.
|
||||
*
|
||||
* Copyright (c) lucko (Luck) <luck@lucko.me>
|
||||
* Copyright (c) contributors
|
||||
*
|
||||
* 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.wrappings;
|
||||
|
||||
import me.lucko.luckperms.common.buffers.Buffer;
|
||||
import me.lucko.luckperms.common.model.Group;
|
||||
import me.lucko.luckperms.common.model.Track;
|
||||
import me.lucko.luckperms.common.model.User;
|
||||
import me.lucko.luckperms.common.storage.Storage;
|
||||
|
||||
import java.lang.reflect.Proxy;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
/**
|
||||
* A storage wrapping that passes save tasks through a buffer
|
||||
*/
|
||||
public interface BufferedOutputStorage extends Storage {
|
||||
|
||||
/**
|
||||
* Creates a new instance of {@link BufferedOutputStorage} which delegates called to the given
|
||||
* {@link Storage} instance.
|
||||
*
|
||||
* @param delegate the delegate storage impl
|
||||
* @param flushTime default flush time for the buffer. See {@link Buffer#flush(long)}
|
||||
* @return the new buffered storage instance
|
||||
*/
|
||||
static BufferedOutputStorage wrap(Storage delegate, long flushTime) {
|
||||
// create a buffer handler - we pass the unwrapped delegate here.
|
||||
StorageBuffer buffer = new StorageBuffer(delegate, flushTime);
|
||||
|
||||
// create and return a proxy instance which directs save calls through the buffer
|
||||
return (BufferedOutputStorage) Proxy.newProxyInstance(
|
||||
BufferedOutputStorage.class.getClassLoader(),
|
||||
new Class[]{BufferedOutputStorage.class},
|
||||
(proxy, method, args) -> {
|
||||
// run save methods through the buffer instance
|
||||
switch (method.getName()) {
|
||||
case "saveUser":
|
||||
return buffer.saveUser((User) args[0]);
|
||||
case "saveGroup":
|
||||
return buffer.saveGroup((Group) args[0]);
|
||||
case "saveTrack":
|
||||
return buffer.saveTrack((Track) args[0]);
|
||||
}
|
||||
|
||||
// provide implementation of #noBuffer
|
||||
if (method.getName().equals("noBuffer")) {
|
||||
return delegate;
|
||||
}
|
||||
|
||||
// provide implementation of #buffer
|
||||
if (method.getName().equals("buffer")) {
|
||||
return buffer;
|
||||
}
|
||||
|
||||
// flush the buffer on shutdown
|
||||
if (method.getName().equals("shutdown")) {
|
||||
buffer.forceFlush();
|
||||
// ...and then delegate
|
||||
}
|
||||
|
||||
// delegate the call
|
||||
return method.invoke(delegate, args);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the buffer behind this instance
|
||||
*
|
||||
* @return the buffer
|
||||
*/
|
||||
StorageBuffer buffer();
|
||||
|
||||
final class StorageBuffer implements Runnable {
|
||||
private final long flushTime;
|
||||
|
||||
private final Buffer<User, Void> userOutputBuffer;
|
||||
private final Buffer<Group, Void> groupOutputBuffer;
|
||||
private final Buffer<Track, Void> trackOutputBuffer;
|
||||
|
||||
private StorageBuffer(Storage delegate, long flushTime) {
|
||||
this.flushTime = flushTime;
|
||||
this.userOutputBuffer = Buffer.of(user -> delegate.saveUser(user).join());
|
||||
this.groupOutputBuffer = Buffer.of(group -> delegate.saveGroup(group).join());
|
||||
this.trackOutputBuffer = Buffer.of(track -> delegate.saveTrack(track).join());
|
||||
}
|
||||
|
||||
public void run() {
|
||||
flush(this.flushTime);
|
||||
}
|
||||
|
||||
public void forceFlush() {
|
||||
flush(-1);
|
||||
}
|
||||
|
||||
public void flush(long flushTime) {
|
||||
this.userOutputBuffer.flush(flushTime);
|
||||
this.groupOutputBuffer.flush(flushTime);
|
||||
this.trackOutputBuffer.flush(flushTime);
|
||||
}
|
||||
|
||||
// copy the required implementation methods from the Storage interface
|
||||
|
||||
private CompletableFuture<Void> saveUser(User user) {
|
||||
return this.userOutputBuffer.enqueue(user);
|
||||
}
|
||||
|
||||
private CompletableFuture<Void> saveGroup(Group group) {
|
||||
return this.groupOutputBuffer.enqueue(group);
|
||||
}
|
||||
|
||||
private CompletableFuture<Void> saveTrack(Track track) {
|
||||
return this.trackOutputBuffer.enqueue(track);
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user