mirror of
https://github.com/LuckPerms/LuckPerms.git
synced 2024-12-29 12:37:40 +01:00
Refactor SQL storage implementation
This commit is contained in:
parent
8fa629a243
commit
a779b31ca5
@ -65,6 +65,7 @@ import java.util.concurrent.ConcurrentSkipListMap;
|
||||
import java.util.concurrent.ConcurrentSkipListSet;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
/**
|
||||
* A map of nodes held by a {@link PermissionHolder}.
|
||||
@ -272,7 +273,7 @@ public final class NodeMap {
|
||||
this.inheritanceMap.remove(context);
|
||||
}
|
||||
|
||||
void setContent(Collection<? extends Node> set) {
|
||||
void setContent(Iterable<? extends Node> set) {
|
||||
this.map.clear();
|
||||
this.inheritanceMap.clear();
|
||||
for (Node n : set) {
|
||||
@ -280,6 +281,12 @@ public final class NodeMap {
|
||||
}
|
||||
}
|
||||
|
||||
void setContent(Stream<? extends Node> stream) {
|
||||
this.map.clear();
|
||||
this.inheritanceMap.clear();
|
||||
stream.forEach(this::add);
|
||||
}
|
||||
|
||||
void setContent(Multimap<ImmutableContextSet, ? extends Node> multimap) {
|
||||
setContent(multimap.values());
|
||||
}
|
||||
|
@ -71,6 +71,7 @@ import java.util.TreeSet;
|
||||
import java.util.concurrent.locks.Lock;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
/**
|
||||
* Represents an object that can hold permissions, (a user or group)
|
||||
@ -233,11 +234,16 @@ public abstract class PermissionHolder {
|
||||
getPlugin().getEventDispatcher().dispatchDataRecalculate(this);
|
||||
}
|
||||
|
||||
public void setNodes(DataType type, Collection<? extends Node> set) {
|
||||
public void setNodes(DataType type, Iterable<? extends Node> set) {
|
||||
getData(type).setContent(set);
|
||||
invalidateCache();
|
||||
}
|
||||
|
||||
public void setNodes(DataType type, Stream<? extends Node> stream) {
|
||||
getData(type).setContent(stream);
|
||||
invalidateCache();
|
||||
}
|
||||
|
||||
public void replaceNodes(DataType type, Multimap<ImmutableContextSet, ? extends Node> multimap) {
|
||||
getData(type).setContent(multimap);
|
||||
invalidateCache();
|
||||
|
@ -46,6 +46,7 @@ import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.concurrent.locks.Lock;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
import java.util.function.Predicate;
|
||||
@ -96,6 +97,7 @@ public final class Track {
|
||||
}
|
||||
|
||||
public void setGroups(List<String> groups) {
|
||||
Objects.requireNonNull(groups, "groups");
|
||||
this.groups.clear();
|
||||
this.groups.addAll(groups);
|
||||
}
|
||||
|
@ -29,6 +29,7 @@ import com.google.common.collect.ImmutableMap;
|
||||
|
||||
import me.lucko.luckperms.common.cache.LoadingMap;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
@ -69,6 +70,13 @@ public abstract class AbstractManager<I, C, T extends C> implements Manager<I, C
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void retainAll(Collection<I> ids) {
|
||||
this.objects.keySet().stream()
|
||||
.filter(g -> !ids.contains(g))
|
||||
.forEach(this::unload);
|
||||
}
|
||||
|
||||
protected I sanitizeIdentifier(I i) {
|
||||
return i;
|
||||
}
|
||||
|
@ -25,6 +25,7 @@
|
||||
|
||||
package me.lucko.luckperms.common.model.manager;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Map;
|
||||
import java.util.function.Function;
|
||||
|
||||
@ -77,4 +78,12 @@ public interface Manager<I, C, T extends C> extends Function<I, T> {
|
||||
*/
|
||||
void unload(I id);
|
||||
|
||||
/**
|
||||
* Calls {@link #unload(Object)} for all objects currently
|
||||
* loaded not in the given collection of ids.
|
||||
*
|
||||
* @param ids the ids to retain
|
||||
*/
|
||||
void retainAll(Collection<I> ids);
|
||||
|
||||
}
|
||||
|
@ -36,7 +36,7 @@ import me.lucko.luckperms.common.model.User;
|
||||
import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
|
||||
import me.lucko.luckperms.common.storage.implementation.StorageImplementation;
|
||||
import me.lucko.luckperms.common.storage.implementation.split.SplitStorage;
|
||||
import me.lucko.luckperms.common.util.ThrowingRunnable;
|
||||
import me.lucko.luckperms.common.util.Throwing;
|
||||
|
||||
import net.luckperms.api.actionlog.Action;
|
||||
import net.luckperms.api.event.cause.CreationCause;
|
||||
@ -92,7 +92,7 @@ public class Storage {
|
||||
}, this.plugin.getBootstrap().getScheduler().async());
|
||||
}
|
||||
|
||||
private CompletableFuture<Void> makeFuture(ThrowingRunnable runnable) {
|
||||
private CompletableFuture<Void> makeFuture(Throwing.Runnable runnable) {
|
||||
return CompletableFuture.runAsync(() -> {
|
||||
try {
|
||||
runnable.run();
|
||||
|
@ -27,13 +27,10 @@ package me.lucko.luckperms.common.storage.implementation.file;
|
||||
|
||||
import me.lucko.luckperms.common.bulkupdate.BulkUpdate;
|
||||
import me.lucko.luckperms.common.bulkupdate.comparison.Constraint;
|
||||
import me.lucko.luckperms.common.model.Group;
|
||||
import me.lucko.luckperms.common.model.Track;
|
||||
import me.lucko.luckperms.common.model.manager.group.GroupManager;
|
||||
import me.lucko.luckperms.common.model.manager.track.TrackManager;
|
||||
import me.lucko.luckperms.common.node.model.HeldNodeImpl;
|
||||
import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
|
||||
import me.lucko.luckperms.common.storage.implementation.file.loader.ConfigurateLoader;
|
||||
import me.lucko.luckperms.common.util.Iterators;
|
||||
|
||||
import net.luckperms.api.node.HeldNode;
|
||||
import net.luckperms.api.node.Node;
|
||||
@ -290,32 +287,17 @@ public class CombinedConfigurateStorage extends AbstractConfigurateStorage {
|
||||
@Override
|
||||
public void loadAllGroups() throws IOException {
|
||||
List<String> groups = new ArrayList<>();
|
||||
|
||||
this.groupsLoader.apply(false, true, root -> {
|
||||
groups.addAll(root.getChildrenMap().keySet().stream()
|
||||
.map(Object::toString)
|
||||
.collect(Collectors.toList()));
|
||||
});
|
||||
|
||||
boolean success = true;
|
||||
for (String g : groups) {
|
||||
try {
|
||||
loadGroup(g);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
success = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (!success) {
|
||||
if (!Iterators.tryIterate(groups, this::loadGroup)) {
|
||||
throw new RuntimeException("Exception occurred whilst loading a group");
|
||||
}
|
||||
|
||||
GroupManager<?> gm = this.plugin.getGroupManager();
|
||||
gm.getAll().values().stream()
|
||||
.map(Group::getName)
|
||||
.filter(g -> !groups.contains(g))
|
||||
.forEach(gm::unload);
|
||||
this.plugin.getGroupManager().retainAll(groups);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -345,32 +327,17 @@ public class CombinedConfigurateStorage extends AbstractConfigurateStorage {
|
||||
@Override
|
||||
public void loadAllTracks() throws IOException {
|
||||
List<String> tracks = new ArrayList<>();
|
||||
|
||||
this.tracksLoader.apply(false, true, root -> {
|
||||
tracks.addAll(root.getChildrenMap().keySet().stream()
|
||||
.map(Object::toString)
|
||||
.collect(Collectors.toList()));
|
||||
});
|
||||
|
||||
boolean success = true;
|
||||
for (String t : tracks) {
|
||||
try {
|
||||
loadTrack(t);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
success = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (!success) {
|
||||
if (!Iterators.tryIterate(tracks, this::loadTrack)) {
|
||||
throw new RuntimeException("Exception occurred whilst loading a track");
|
||||
}
|
||||
|
||||
TrackManager<?> tm = this.plugin.getTrackManager();
|
||||
tm.getAll().values().stream()
|
||||
.map(Track::getName)
|
||||
.filter(t -> !tracks.contains(t))
|
||||
.forEach(tm::unload);
|
||||
this.plugin.getTrackManager().retainAll(tracks);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -27,14 +27,11 @@ package me.lucko.luckperms.common.storage.implementation.file;
|
||||
|
||||
import me.lucko.luckperms.common.bulkupdate.BulkUpdate;
|
||||
import me.lucko.luckperms.common.bulkupdate.comparison.Constraint;
|
||||
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.model.manager.group.GroupManager;
|
||||
import me.lucko.luckperms.common.model.manager.track.TrackManager;
|
||||
import me.lucko.luckperms.common.node.model.HeldNodeImpl;
|
||||
import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
|
||||
import me.lucko.luckperms.common.storage.implementation.file.loader.ConfigurateLoader;
|
||||
import me.lucko.luckperms.common.util.Iterators;
|
||||
import me.lucko.luckperms.common.util.MoreFiles;
|
||||
import me.lucko.luckperms.common.util.Uuids;
|
||||
|
||||
@ -292,25 +289,11 @@ public class SeparatedConfigurateStorage extends AbstractConfigurateStorage {
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
boolean success = true;
|
||||
for (String g : groups) {
|
||||
try {
|
||||
loadGroup(g);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
success = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (!success) {
|
||||
if (!Iterators.tryIterate(groups, this::loadGroup)) {
|
||||
throw new RuntimeException("Exception occurred whilst loading a group");
|
||||
}
|
||||
|
||||
GroupManager<?> gm = this.plugin.getGroupManager();
|
||||
gm.getAll().values().stream()
|
||||
.map(Group::getName)
|
||||
.filter(g -> !groups.contains(g))
|
||||
.forEach(gm::unload);
|
||||
this.plugin.getGroupManager().retainAll(groups);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -349,25 +332,11 @@ public class SeparatedConfigurateStorage extends AbstractConfigurateStorage {
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
boolean success = true;
|
||||
for (String t : tracks) {
|
||||
try {
|
||||
loadTrack(t);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
success = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (!success) {
|
||||
if (!Iterators.tryIterate(tracks, this::loadTrack)) {
|
||||
throw new RuntimeException("Exception occurred whilst loading a track");
|
||||
}
|
||||
|
||||
TrackManager<?> tm = this.plugin.getTrackManager();
|
||||
tm.getAll().values().stream()
|
||||
.map(Track::getName)
|
||||
.filter(t -> !tracks.contains(t))
|
||||
.forEach(tm::unload);
|
||||
this.plugin.getTrackManager().retainAll(tracks);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -46,13 +46,13 @@ 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.model.manager.group.GroupManager;
|
||||
import me.lucko.luckperms.common.model.manager.track.TrackManager;
|
||||
import me.lucko.luckperms.common.node.factory.NodeBuilders;
|
||||
import me.lucko.luckperms.common.node.model.HeldNodeImpl;
|
||||
import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
|
||||
import me.lucko.luckperms.common.storage.implementation.StorageImplementation;
|
||||
import me.lucko.luckperms.common.storage.misc.PlayerSaveResultImpl;
|
||||
import me.lucko.luckperms.common.storage.misc.StorageCredentials;
|
||||
import me.lucko.luckperms.common.util.Iterators;
|
||||
|
||||
import net.luckperms.api.actionlog.Action;
|
||||
import net.luckperms.api.context.Context;
|
||||
@ -442,25 +442,11 @@ public class MongoStorage implements StorageImplementation {
|
||||
}
|
||||
}
|
||||
|
||||
boolean success = true;
|
||||
for (String g : groups) {
|
||||
try {
|
||||
loadGroup(g);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
success = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (!success) {
|
||||
if (!Iterators.tryIterate(groups, this::loadGroup)) {
|
||||
throw new RuntimeException("Exception occurred whilst loading a group");
|
||||
}
|
||||
|
||||
GroupManager<?> gm = this.plugin.getGroupManager();
|
||||
gm.getAll().values().stream()
|
||||
.map(Group::getName)
|
||||
.filter(g -> !groups.contains(g))
|
||||
.forEach(gm::unload);
|
||||
this.plugin.getGroupManager().retainAll(groups);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -569,25 +555,11 @@ public class MongoStorage implements StorageImplementation {
|
||||
}
|
||||
}
|
||||
|
||||
boolean success = true;
|
||||
for (String t : tracks) {
|
||||
try {
|
||||
loadTrack(t);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
success = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (!success) {
|
||||
if (!Iterators.tryIterate(tracks, this::loadTrack)) {
|
||||
throw new RuntimeException("Exception occurred whilst loading a track");
|
||||
}
|
||||
|
||||
TrackManager<?> tm = this.plugin.getTrackManager();
|
||||
tm.getAll().values().stream()
|
||||
.map(Track::getName)
|
||||
.filter(t -> !tracks.contains(t))
|
||||
.forEach(tm::unload);
|
||||
this.plugin.getTrackManager().retainAll(tracks);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -0,0 +1,69 @@
|
||||
/*
|
||||
* 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.implementation.sql;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
public final class SchemaReader {
|
||||
private SchemaReader() {}
|
||||
|
||||
public static List<String> getStatements(InputStream is) throws IOException {
|
||||
List<String> queries = new LinkedList<>();
|
||||
|
||||
try (BufferedReader reader = new BufferedReader(new InputStreamReader(is, StandardCharsets.UTF_8))) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
String line;
|
||||
while ((line = reader.readLine()) != null) {
|
||||
if (line.startsWith("--") || line.startsWith("#")) {
|
||||
continue;
|
||||
}
|
||||
|
||||
sb.append(line);
|
||||
|
||||
// check for end of declaration
|
||||
if (line.endsWith(";")) {
|
||||
sb.deleteCharAt(sb.length() - 1);
|
||||
|
||||
String result = sb.toString().trim();
|
||||
if (!result.isEmpty()) {
|
||||
queries.add(result);
|
||||
}
|
||||
|
||||
// reset
|
||||
sb = new StringBuilder();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return queries;
|
||||
}
|
||||
}
|
@ -47,6 +47,8 @@ import java.util.Set;
|
||||
*/
|
||||
public final class SqlNode {
|
||||
|
||||
public static final int NULL_ID = -1;
|
||||
|
||||
public static SqlNode fromNode(Node node) {
|
||||
ContextSet contexts = node.getContexts();
|
||||
|
||||
@ -78,11 +80,7 @@ public final class SqlNode {
|
||||
|
||||
|
||||
long expiry = node.hasExpiry() ? node.getExpiry().getEpochSecond() : 0L;
|
||||
return new SqlNode(node.getKey(), node.getValue(), server, world, expiry, contexts.immutableCopy(), -1);
|
||||
}
|
||||
|
||||
public static SqlNode fromSqlFields(String permission, boolean value, String server, String world, long expiry, String contexts) {
|
||||
return new SqlNode(permission, value, server, world, expiry, ContextSetJsonSerializer.deserializeContextSet(GsonProvider.normal(), contexts).immutableCopy(), -1);
|
||||
return new SqlNode(node.getKey(), node.getValue(), server, world, expiry, contexts.immutableCopy(), NULL_ID);
|
||||
}
|
||||
|
||||
public static SqlNode fromSqlFields(long sqlId, String permission, boolean value, String server, String world, long expiry, String contexts) {
|
||||
@ -142,7 +140,7 @@ public final class SqlNode {
|
||||
}
|
||||
|
||||
public long getSqlId() {
|
||||
if (this.sqlId == -1) {
|
||||
if (this.sqlId == NULL_ID) {
|
||||
throw new IllegalStateException("sql id not set");
|
||||
}
|
||||
return this.sqlId;
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -34,44 +34,56 @@ import java.util.function.Function;
|
||||
public final class Iterators {
|
||||
private Iterators() {}
|
||||
|
||||
public static <E> void tryIterate(Iterable<E> iterable, Consumer<E> action) {
|
||||
public static <E> boolean tryIterate(Iterable<E> iterable, Throwing.Consumer<E> action) {
|
||||
boolean success = true;
|
||||
for (E element : iterable) {
|
||||
try {
|
||||
action.accept(element);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
success = false;
|
||||
}
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
public static <I, O> void tryIterate(Iterable<I> iterable, Function<I, O> mapping, Consumer<O> action) {
|
||||
public static <I, O> boolean tryIterate(Iterable<I> iterable, Function<I, O> mapping, Consumer<O> action) {
|
||||
boolean success = true;
|
||||
for (I element : iterable) {
|
||||
try {
|
||||
action.accept(mapping.apply(element));
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
success = false;
|
||||
}
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
public static <E> void tryIterate(E[] array, Consumer<E> action) {
|
||||
public static <E> boolean tryIterate(E[] array, Consumer<E> action) {
|
||||
boolean success = true;
|
||||
for (E element : array) {
|
||||
try {
|
||||
action.accept(element);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
success = false;
|
||||
}
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
public static <I, O> void tryIterate(I[] array, Function<I, O> mapping, Consumer<O> action) {
|
||||
public static <I, O> boolean tryIterate(I[] array, Function<I, O> mapping, Consumer<O> action) {
|
||||
boolean success = true;
|
||||
for (I element : array) {
|
||||
try {
|
||||
action.accept(mapping.apply(element));
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
success = false;
|
||||
}
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
public static <E> List<List<E>> divideIterable(Iterable<E> source, int size) {
|
||||
|
@ -25,8 +25,15 @@
|
||||
|
||||
package me.lucko.luckperms.common.util;
|
||||
|
||||
public interface ThrowingRunnable {
|
||||
public interface Throwing {
|
||||
|
||||
void run() throws Exception;
|
||||
@FunctionalInterface
|
||||
interface Runnable {
|
||||
void run() throws Exception;
|
||||
}
|
||||
|
||||
@FunctionalInterface
|
||||
interface Consumer<T> {
|
||||
void accept(T t) throws Exception;
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user