Add support for split storage

This commit is contained in:
Luck 2016-08-31 09:30:19 +01:00
parent 5c19dd8b15
commit 3fd62a80e2
No known key found for this signature in database
GPG Key ID: EFA9B3EC5FD90F8B
7 changed files with 244 additions and 27 deletions

View File

@ -47,6 +47,18 @@ log-notify: true
# Fill out connection info below if you're using MySQL or MongoDB
storage-method: h2
# This block enables support for split datastores.
# Only touch this if you're sure that you know what you're doing.
# I (the author) do not endorse nor recommend the use of this feature.
split-storage:
enabled: false
methods:
user: h2
group: h2
track: h2
uuid: h2
log: h2
data:
address: localhost:3306
database: minecraft

View File

@ -47,6 +47,18 @@ log-notify: true
# Fill out connection info below if you're using MySQL or MongoDB
storage-method: h2
# This block enables support for split datastores.
# Only touch this if you're sure that you know what you're doing.
# I (the author) do not endorse nor recommend the use of this feature.
split-storage:
enabled: false
methods:
user: h2
group: h2
track: h2
uuid: h2
log: h2
data:
address: localhost:3306
database: minecraft

View File

@ -28,6 +28,9 @@ import me.lucko.luckperms.LuckPermsPlugin;
import me.lucko.luckperms.constants.Patterns;
import me.lucko.luckperms.storage.DatastoreConfiguration;
import java.util.HashMap;
import java.util.Map;
public abstract class LPConfiguration<T extends LuckPermsPlugin> {
@Getter(AccessLevel.PROTECTED)
@ -118,4 +121,19 @@ public abstract class LPConfiguration<T extends LuckPermsPlugin> {
public String getStorageMethod() {
return getString("storage-method", defaultStorage);
}
public boolean getSplitStorage() {
return getBoolean("split-storage.enabled", false);
}
public Map<String, String> getSplitStorageOptions() {
Map<String, String> map = new HashMap<>();
map.put("user", getString("split-storage.methods.user", defaultStorage));
map.put("group", getString("split-storage.methods.group", defaultStorage));
map.put("track", getString("split-storage.methods.track", defaultStorage));
map.put("uuid", getString("split-storage.methods.uuid", defaultStorage));
map.put("log", getString("split-storage.methods.log", defaultStorage));
return map;
}
}

View File

@ -0,0 +1,136 @@
package me.lucko.luckperms.storage;
import com.google.common.collect.ImmutableMap;
import me.lucko.luckperms.LuckPermsPlugin;
import me.lucko.luckperms.api.LogEntry;
import me.lucko.luckperms.data.Log;
import me.lucko.luckperms.groups.Group;
import me.lucko.luckperms.tracks.Track;
import me.lucko.luckperms.users.User;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
public class SplitDatastore extends Datastore {
private final Map<String, Datastore> backing;
private final Map<String, String> types;
protected SplitDatastore(LuckPermsPlugin plugin, Map<String, Datastore> backing, Map<String, String> types) {
super(plugin, "Split Storage");
this.backing = ImmutableMap.copyOf(backing);
this.types = ImmutableMap.copyOf(types);
}
@Override
public void init() {
backing.values().forEach(Datastore::init);
for (Datastore ds : backing.values()) {
if (!ds.isAcceptingLogins()) {
return;
}
}
setAcceptingLogins(true);
}
@Override
public void shutdown() {
backing.values().forEach(Datastore::shutdown);
}
@Override
public boolean logAction(LogEntry entry) {
return backing.get(types.get("log")).logAction(entry);
}
@Override
public Log getLog() {
return backing.get(types.get("log")).getLog();
}
@Override
public boolean loadUser(UUID uuid, String username) {
return backing.get(types.get("user")).loadUser(uuid, username);
}
@Override
public boolean saveUser(User user) {
return backing.get(types.get("user")).saveUser(user);
}
@Override
public boolean cleanupUsers() {
return backing.get(types.get("user")).cleanupUsers();
}
@Override
public Set<UUID> getUniqueUsers() {
return backing.get(types.get("user")).getUniqueUsers();
}
@Override
public boolean createAndLoadGroup(String name) {
return backing.get(types.get("group")).createAndLoadGroup(name);
}
@Override
public boolean loadGroup(String name) {
return backing.get(types.get("group")).loadGroup(name);
}
@Override
public boolean loadAllGroups() {
return backing.get(types.get("group")).loadAllGroups();
}
@Override
public boolean saveGroup(Group group) {
return backing.get(types.get("group")).saveGroup(group);
}
@Override
public boolean deleteGroup(Group group) {
return backing.get(types.get("group")).deleteGroup(group);
}
@Override
public boolean createAndLoadTrack(String name) {
return backing.get(types.get("track")).createAndLoadTrack(name);
}
@Override
public boolean loadTrack(String name) {
return backing.get(types.get("track")).loadTrack(name);
}
@Override
public boolean loadAllTracks() {
return backing.get(types.get("track")).loadAllTracks();
}
@Override
public boolean saveTrack(Track track) {
return backing.get(types.get("track")).saveTrack(track);
}
@Override
public boolean deleteTrack(Track track) {
return backing.get(types.get("track")).deleteTrack(track);
}
@Override
public boolean saveUUIDData(String username, UUID uuid) {
return backing.get(types.get("uuid")).saveUUIDData(username, uuid);
}
@Override
public UUID getUUID(String username) {
return backing.get(types.get("uuid")).getUUID(username);
}
@Override
public String getName(UUID uuid) {
return backing.get(types.get("uuid")).getName(uuid);
}
}

View File

@ -28,48 +28,73 @@ import me.lucko.luckperms.LuckPermsPlugin;
import me.lucko.luckperms.storage.methods.*;
import java.io.File;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
@UtilityClass
public class StorageFactory {
private static final Set<String> TYPES = ImmutableSet.of("flatfile", "mongodb", "mysql", "sqlite", "h2");
@SuppressWarnings("unchecked")
public static Datastore getDatastore(LuckPermsPlugin plugin, String defaultMethod) {
Datastore datastore;
plugin.getLog().info("Detecting storage method...");
String storageMethod = plugin.getConfiguration().getStorageMethod().toLowerCase();
if (plugin.getConfiguration().getSplitStorage()) {
plugin.getLog().info("Using split storage.");
if (!TYPES.contains(storageMethod)) {
plugin.getLog().severe("Storage method '" + storageMethod + "' not recognised. Using the default instead.");
storageMethod = defaultMethod;
}
// java sucks
Map<String, String> types = (Map<String, String>) plugin.getConfiguration().getSplitStorageOptions();
switch (storageMethod) {
case "mysql":
plugin.getLog().info("Using MySQL as storage method.");
datastore = new MySQLDatastore(plugin, plugin.getConfiguration().getDatabaseValues());
break;
case "sqlite":
plugin.getLog().info("Using SQLite as storage method.");
datastore = new SQLiteDatastore(plugin, new File(plugin.getDataFolder(), "luckperms.sqlite"));
break;
case "h2":
plugin.getLog().info("Using H2 as storage method.");
datastore = new H2Datastore(plugin, new File(plugin.getDataFolder(), "luckperms.db"));
break;
case "mongodb":
plugin.getLog().info("Using MongoDB as storage method.");
datastore = new MongoDBDatastore(plugin, plugin.getConfiguration().getDatabaseValues());
break;
default:
plugin.getLog().info("Using Flatfile (JSON) as storage method.");
datastore = new FlatfileDatastore(plugin, plugin.getDataFolder());
break;
types.entrySet().stream()
.filter(e -> !TYPES.contains(e.getValue().toLowerCase()))
.forEach(e -> {
plugin.getLog().severe("Storage method for " + e.getKey() + " - " + e.getValue() + " not recognised. " +
"Using the default instead.");
e.setValue(defaultMethod);
});
Set<String> neededTypes = new HashSet<>();
neededTypes.addAll(types.values());
Map<String, Datastore> backing = new HashMap<>();
for (String type : neededTypes) {
backing.put(type, fromString(type, plugin));
}
datastore = new SplitDatastore(plugin, backing, types);
} else {
String storageMethod = plugin.getConfiguration().getStorageMethod().toLowerCase();
if (!TYPES.contains(storageMethod)) {
plugin.getLog().severe("Storage method '" + storageMethod + "' not recognised. Using the default instead.");
storageMethod = defaultMethod;
}
datastore = fromString(storageMethod, plugin);
plugin.getLog().info("Using " + datastore.getName() + " as storage method.");
}
plugin.getLog().info("Initialising datastore...");
datastore.init();
return datastore;
}
private static Datastore fromString(String storageMethod, LuckPermsPlugin plugin) {
switch (storageMethod) {
case "mysql":
return new MySQLDatastore(plugin, plugin.getConfiguration().getDatabaseValues());
case "sqlite":
return new SQLiteDatastore(plugin, new File(plugin.getDataFolder(), "luckperms.sqlite"));
case "h2":
return new H2Datastore(plugin, new File(plugin.getDataFolder(), "luckperms.db"));
case "mongodb":
return new MongoDBDatastore(plugin, plugin.getConfiguration().getDatabaseValues());
default:
return new FlatfileDatastore(plugin, plugin.getDataFolder());
}
}
}

View File

@ -66,7 +66,7 @@ public class SQLiteDatastore extends SQLDatastore {
@Cleanup PreparedStatement preparedStatement = connection.prepareStatement(queryPS.getQuery());
queryPS.onRun(preparedStatement);
preparedStatement.execute();
success = true;
} catch (SQLException e) {
e.printStackTrace();

View File

@ -47,6 +47,20 @@ log-notify=true
# Fill out connection info below if you're using MySQL or MongoDB
storage-method="h2"
# This block enables support for split datastores.
# Only touch this if you're sure that you know what you're doing.
# I (the author) do not endorse nor recommend the use of this feature.
split-storage: {
enabled=false
methods: {
user="h2"
group="h2"
track="h2"
uuid="h2"
log="h2"
}
}
data: {
address="localhost:3306"
database="minecraft"