#1147 Drop SingleFilePersistenceHandler in favor of DistributedFilesPersistenceHandler

- Remove SingleFilePersistenceHandler: DistributedFilesPersistenceHandler with segment size 1 can be used instead
- Rename  SegmentFilesPersistenceHolder to DistributedFilesPersistenceHandler
- Rename SeparateFilePersistenceHandler to IndividualFilesPersistenceHandler to match LimboPersistenceType entry
- Add link to limbo page on Wiki in the settings
This commit is contained in:
ljacqu
2017-03-28 21:42:01 +02:00
parent a764598f88
commit adb007108d
10 changed files with 47 additions and 140 deletions
@@ -30,7 +30,7 @@ import java.util.Optional;
* Persistence handler for LimboPlayer objects by distributing the objects to store
* in various segments (buckets) based on the start of the player's UUID.
*/
class SegmentFilesPersistenceHolder implements LimboPersistenceHandler {
class DistributedFilesPersistenceHandler implements LimboPersistenceHandler {
private static final Type LIMBO_MAP_TYPE = new TypeToken<Map<String, LimboPlayer>>(){}.getType();
@@ -39,7 +39,7 @@ class SegmentFilesPersistenceHolder implements LimboPersistenceHandler {
private final SegmentNameBuilder segmentNameBuilder;
@Inject
SegmentFilesPersistenceHolder(@DataFolder File dataFolder, BukkitService bukkitService, Settings settings) {
DistributedFilesPersistenceHandler(@DataFolder File dataFolder, BukkitService bukkitService, Settings settings) {
cacheFolder = new File(dataFolder, "playerdata");
if (!cacheFolder.exists()) {
// TODO ljacqu 20170313: Create FileUtils#mkdirs
@@ -100,7 +100,7 @@ class SegmentFilesPersistenceHolder implements LimboPersistenceHandler {
@Override
public LimboPersistenceType getType() {
return LimboPersistenceType.SEGMENT_FILES;
return LimboPersistenceType.DISTRIBUTED_FILES;
}
private void saveEntries(Map<String, LimboPlayer> entries, File file) {
@@ -126,7 +126,11 @@ class SegmentFilesPersistenceHolder implements LimboPersistenceHandler {
private File getPlayerSegmentFile(String uuid) {
String segment = segmentNameBuilder.createSegmentName(uuid);
return new File(cacheFolder, segment + "-limbo.json");
return getSegmentFile(segment);
}
private File getSegmentFile(String segmentId) {
return new File(cacheFolder, segmentId + "-limbo.json");
}
/**
@@ -167,7 +171,7 @@ class SegmentFilesPersistenceHolder implements LimboPersistenceHandler {
ConsoleLogger.info("Saving " + limbosFromOldSegments.size() + " LimboPlayers from old segments into "
+ limboBySegment.size() + " current segments");
for (Map.Entry<String, Map<String, LimboPlayer>> entry : limboBySegment.entrySet()) {
File file = new File(cacheFolder, entry.getKey() + "-limbo.json");
File file = getSegmentFile(entry.getKey());
Map<String, LimboPlayer> limbosToSave = Optional.ofNullable(readLimboPlayers(file))
.orElseGet(HashMap::new);
limbosToSave.putAll(entry.getValue());
@@ -193,7 +197,7 @@ class SegmentFilesPersistenceHolder implements LimboPersistenceHandler {
}
/**
* Deletes files from the current segmenting scheme that are empty.
* Deletes segment files that are empty.
*/
private void deleteEmptyFiles() {
File[] files = listFiles(cacheFolder);
@@ -19,13 +19,13 @@ import java.nio.charset.StandardCharsets;
/**
* Saves LimboPlayer objects as JSON into individual files.
*/
class SeparateFilePersistenceHandler implements LimboPersistenceHandler {
class IndividualFilesPersistenceHandler implements LimboPersistenceHandler {
private final Gson gson;
private final File cacheDir;
@Inject
SeparateFilePersistenceHandler(@DataFolder File dataFolder, BukkitService bukkitService) {
IndividualFilesPersistenceHandler(@DataFolder File dataFolder, BukkitService bukkitService) {
cacheDir = new File(dataFolder, "playerdata");
if (!cacheDir.exists() && !cacheDir.isDirectory() && !cacheDir.mkdir()) {
ConsoleLogger.warning("Failed to create playerdata directory '" + cacheDir + "'");
@@ -6,13 +6,10 @@ package fr.xephi.authme.data.limbo.persistence;
public enum LimboPersistenceType {
/** Store each LimboPlayer in a separate file. */
INDIVIDUAL_FILES(SeparateFilePersistenceHandler.class),
INDIVIDUAL_FILES(IndividualFilesPersistenceHandler.class),
/** Store all LimboPlayers in the same file. */
SINGLE_FILE(SingleFilePersistenceHandler.class),
/** Distribute LimboPlayers by segments into a set number of files. */
SEGMENT_FILES(SegmentFilesPersistenceHolder.class),
/** Store LimboPlayers distributed in a configured number of files. */
DISTRIBUTED_FILES(DistributedFilesPersistenceHandler.class),
/** No persistence to disk. */
DISABLED(NoOpPersistenceHandler.class);
@@ -3,7 +3,7 @@ package fr.xephi.authme.data.limbo.persistence;
/**
* Configuration for the total number of segments to use.
* <p>
* The {@link SegmentFilesPersistenceHolder} reduces the number of files by assigning each UUID
* The {@link DistributedFilesPersistenceHandler} reduces the number of files by assigning each UUID
* to a segment. This enum allows to define how many segments the UUIDs should be distributed in.
* <p>
* Segments are defined by a <b>distribution</b> and a <b>length.</b> The distribution defines
@@ -38,8 +38,8 @@ public enum SegmentConfiguration {
/** 1. */
ONE(1, 1),
///** 2. */
//TWO(2, 1),
// /** 2. */
// TWO(2, 1),
/** 4. */
FOUR(4, 1),
@@ -86,7 +86,7 @@ public enum SegmentConfiguration {
}
/**
* @return number of segments to which this configuration will distribute UUIDs
* @return number of segments to which this configuration will distribute all UUIDs
*/
public int getTotalSegments() {
return (int) Math.pow(distribution, length);
@@ -4,7 +4,7 @@ import java.util.HashMap;
import java.util.Map;
/**
* Creates segment names for {@link SegmentFilesPersistenceHolder}.
* Creates segment names for {@link DistributedFilesPersistenceHandler}.
*/
class SegmentNameBuilder {
@@ -1,94 +0,0 @@
package fr.xephi.authme.data.limbo.persistence;
import com.google.common.reflect.TypeToken;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import fr.xephi.authme.ConsoleLogger;
import fr.xephi.authme.data.limbo.LimboPlayer;
import fr.xephi.authme.initialization.DataFolder;
import fr.xephi.authme.service.BukkitService;
import fr.xephi.authme.util.FileUtils;
import fr.xephi.authme.util.PlayerUtils;
import org.bukkit.entity.Player;
import javax.inject.Inject;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.lang.reflect.Type;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
/**
* Saves all LimboPlayers in one JSON file and keeps the entries in memory.
*/
class SingleFilePersistenceHandler implements LimboPersistenceHandler {
private final File cacheFile;
private final Gson gson;
private Map<String, LimboPlayer> entries;
@Inject
SingleFilePersistenceHandler(@DataFolder File dataFolder, BukkitService bukkitService) {
cacheFile = new File(dataFolder, "limbo.json");
if (!cacheFile.exists()) {
FileUtils.create(cacheFile);
}
gson = new GsonBuilder()
.registerTypeAdapter(LimboPlayer.class, new LimboPlayerSerializer())
.registerTypeAdapter(LimboPlayer.class, new LimboPlayerDeserializer(bukkitService))
.setPrettyPrinting()
.create();
Type type = new TypeToken<ConcurrentMap<String, LimboPlayer>>(){}.getType();
try (FileReader fr = new FileReader(cacheFile)) {
entries = gson.fromJson(fr, type);
} catch (IOException e) {
ConsoleLogger.logException("Failed to read from '" + cacheFile + "':", e);
}
if (entries == null) {
entries = new ConcurrentHashMap<>();
}
}
@Override
public LimboPlayer getLimboPlayer(Player player) {
return entries.get(PlayerUtils.getUUIDorName(player));
}
@Override
public void saveLimboPlayer(Player player, LimboPlayer limbo) {
entries.put(PlayerUtils.getUUIDorName(player), limbo);
saveEntries("adding '" + player.getName() + "'");
}
@Override
public void removeLimboPlayer(Player player) {
LimboPlayer entry = entries.remove(PlayerUtils.getUUIDorName(player));
if (entry != null) {
saveEntries("removing '" + player.getName() + "'");
}
}
/**
* Saves the entries to the disk.
*
* @param action the reason for saving (for logging purposes)
*/
private void saveEntries(String action) {
try (FileWriter fw = new FileWriter(cacheFile)) {
gson.toJson(entries, fw);
} catch (IOException e) {
ConsoleLogger.logException("Failed saving JSON limbo cache after " + action, e);
}
}
@Override
public LimboPersistenceType getType() {
return LimboPersistenceType.SINGLE_FILE;
}
}