From 8409a5ed8e6fd1421c4acb27908ddde7e2d1eca7 Mon Sep 17 00:00:00 2001 From: labalityowo <56186498+labalityowo@users.noreply.github.com> Date: Fri, 19 May 2023 11:54:18 +0700 Subject: [PATCH] what the fuck? no one complained these were missing lmao --- .../serverdata/servers/ConnectionData.java | 54 ++++++ .../servers/DedicatedServerSorter.java | 20 +++ .../serverdata/servers/ServerManager.java | 170 ++++++++++++++++++ .../serverdata/servers/ServerRepository.java | 81 +++++++++ .../serverdata/servers/ConnectionData.java | 54 ++++++ .../servers/DedicatedServerSorter.java | 20 +++ .../serverdata/servers/ServerManager.java | 170 ++++++++++++++++++ .../serverdata/servers/ServerRepository.java | 81 +++++++++ 8 files changed, 650 insertions(+) create mode 100644 Plugins[Modified]/Mineplex.ServerData/src/mineplex/serverdata/servers/ConnectionData.java create mode 100644 Plugins[Modified]/Mineplex.ServerData/src/mineplex/serverdata/servers/DedicatedServerSorter.java create mode 100644 Plugins[Modified]/Mineplex.ServerData/src/mineplex/serverdata/servers/ServerManager.java create mode 100644 Plugins[Modified]/Mineplex.ServerData/src/mineplex/serverdata/servers/ServerRepository.java create mode 100644 Plugins[Original]/Mineplex.ServerData/src/mineplex/serverdata/servers/ConnectionData.java create mode 100644 Plugins[Original]/Mineplex.ServerData/src/mineplex/serverdata/servers/DedicatedServerSorter.java create mode 100644 Plugins[Original]/Mineplex.ServerData/src/mineplex/serverdata/servers/ServerManager.java create mode 100644 Plugins[Original]/Mineplex.ServerData/src/mineplex/serverdata/servers/ServerRepository.java diff --git a/Plugins[Modified]/Mineplex.ServerData/src/mineplex/serverdata/servers/ConnectionData.java b/Plugins[Modified]/Mineplex.ServerData/src/mineplex/serverdata/servers/ConnectionData.java new file mode 100644 index 00000000..e7c8676d --- /dev/null +++ b/Plugins[Modified]/Mineplex.ServerData/src/mineplex/serverdata/servers/ConnectionData.java @@ -0,0 +1,54 @@ +package mineplex.serverdata.servers; + +/** + * ConnectionData stores information relevant for initiating a connection to a repository. + * @author MrTwiggy + * + */ +public class ConnectionData +{ + + public enum ConnectionType + { + MASTER, + SLAVE; + } + + private ConnectionType _type; // The type of connection available + public ConnectionType getType() { return _type; } + + private String _name; // The name associated with this connection + public String getName() { return _name; } + + private String _host; // The host URL to connect to repository + public String getHost() { return _host; } + + private int _port; // The port to connect to repository + public int getPort() { return _port; } + + /** + * Constructor + * @param host - the host URL defining the repository + * @param port - the port used for connection to repository + * @param type - the type of connection referenced by this ConnectionData + * @param name - the name associated with ConnectionData + */ + public ConnectionData(String host, int port, ConnectionType type, String name) + { + _host = host; + _port = port; + _type = type; + _name = name; + } + + /** + * @param name + * @return true, if {@code name} is null or it matches (case-insensitive) the {@code _name} associated + * with this ConnectionData, false otherwise. + */ + public boolean nameMatches(String name) + { + return (name == null || name.equalsIgnoreCase(_name)); + } +} + diff --git a/Plugins[Modified]/Mineplex.ServerData/src/mineplex/serverdata/servers/DedicatedServerSorter.java b/Plugins[Modified]/Mineplex.ServerData/src/mineplex/serverdata/servers/DedicatedServerSorter.java new file mode 100644 index 00000000..8f5b6853 --- /dev/null +++ b/Plugins[Modified]/Mineplex.ServerData/src/mineplex/serverdata/servers/DedicatedServerSorter.java @@ -0,0 +1,20 @@ +package mineplex.serverdata.servers; + +import java.util.Comparator; + +import mineplex.serverdata.data.DedicatedServer; + +public class DedicatedServerSorter implements Comparator +{ + @Override + public int compare(DedicatedServer first, DedicatedServer second) + { + if (second.getAvailableRam() <= 1024) return -1; + else if (first.getAvailableRam() <= 1024) return 1; + else if (first.getAvailableRam() > second.getAvailableRam()) return -1; + else if (second.getAvailableRam() > first.getAvailableRam()) return 1; + else if (first.getAvailableCpu() > second.getAvailableCpu()) return -1; + else if (second.getAvailableCpu() > first.getAvailableCpu()) return 1; + else return 0; + } +} \ No newline at end of file diff --git a/Plugins[Modified]/Mineplex.ServerData/src/mineplex/serverdata/servers/ServerManager.java b/Plugins[Modified]/Mineplex.ServerData/src/mineplex/serverdata/servers/ServerManager.java new file mode 100644 index 00000000..20324fe1 --- /dev/null +++ b/Plugins[Modified]/Mineplex.ServerData/src/mineplex/serverdata/servers/ServerManager.java @@ -0,0 +1,170 @@ +package mineplex.serverdata.servers; + +import java.io.File; +import java.nio.charset.Charset; +import java.nio.file.Files; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Random; + +import mineplex.serverdata.Region; +import mineplex.serverdata.redis.RedisConfig; +import mineplex.serverdata.redis.RedisServerRepository; +import mineplex.serverdata.servers.ConnectionData.ConnectionType; + +/** + * ServerManager handles the creation/management of {@link ServerRepository}s for use. + * @author Ty + * + */ +public class ServerManager +{ + public static final String SERVER_STATUS_LABEL = "ServerStatus"; // Label differentiating ServerStatus related servers + private static final String DEFAULT_CONFIG = "redis-config.dat"; + + // Configuration determining connection information + private static RedisConfig _config; + + // The cached repository instances + private static Map repositories = new HashMap(); + + /** + * @param host - the host url used to connect to the database + * @param port - the port to connect to the repository + * @param region - the geographical region of the {@link ServerRepository}. + * @return a newly instanced (or cached) {@link ServerRepository} for the specified {@code region}. + */ + private static ServerRepository getServerRepository(ConnectionData writeConn, ConnectionData readConn, Region region) + { + if (repositories.containsKey(region)) return repositories.get(region); + + ServerRepository repository = new RedisServerRepository(writeConn, readConn, region); + repositories.put(region, repository); + return repository; + } + + /** + * {@code host} defaults to {@value DEFAULT_REDIS_HOST} and + * {@code port} defaults to {@value DEFAULT_REDIS_PORT}. + * + * @see #getServerRepository(String, int, Region) + */ + public static ServerRepository getServerRepository(Region region) + { + return getServerRepository(getConnection(true, SERVER_STATUS_LABEL), getConnection(false, SERVER_STATUS_LABEL), region); + } + + /** + * @return the {@link ConnectionData} associated with the master instance connection. + */ + public static ConnectionData getMasterConnection() + { + return getConnection(true); + } + + /** + * Non-Deterministic: Generates random slave instance connection. + * @return the {@link ConnectionData} associated with a random slave connection. + */ + public static ConnectionData getSlaveConnection() + { + return getConnection(false); + } + + public static ConnectionData getConnection(boolean writeable, String name) + { + return getDefaultConfig().getConnection(writeable, name); + } + + /** + * @param writeable - whether the connection referenced in return can receive write-requests + * @return a newly generated {@code ConnectionData} pointing to a valid connection. + */ + public static ConnectionData getConnection(boolean writeable) + { + return getConnection(writeable, "DefaultConnection"); + } + + /** + * @return the default {@link RedisConfig} associated with this manager, providing appropriate connections. + */ + public static RedisConfig getDefaultConfig() + { + return getConfig(DEFAULT_CONFIG); + } + + /** + * @return the {@link RedisConfig} associated with this manager, providing appropriate connections. + */ + public static RedisConfig getConfig(String fileName) + { + if (_config == null) + _config = loadConfig(fileName); + + return _config; + } + + public static RedisConfig loadConfig(String fileName) + { + try + { + File configFile = new File(fileName); + + if (configFile.exists()) + { + List connections = new ArrayList(); + List lines = Files.readAllLines(configFile.toPath(), Charset.defaultCharset()); + + for (String line : lines) + { + ConnectionData connection = deserializeConnection(line); + connections.add(connection); + + } + + return new RedisConfig(connections); + } + else + { + log(fileName + " not found at " + configFile.toPath().toString()); + return new RedisConfig(); + } + } + catch (Exception exception) + { + exception.printStackTrace(); + log("---Unable To Parse Redis Configuration File---"); + } + + return null; + } + + /** + * @param line - the serialized line representing a valid {@link ConnectionData} object. + * @return a deserialized {@link ConnectionData} referenced by the {@code line} passed in. + */ + private static ConnectionData deserializeConnection(String line) + { + String[] args = line.split(" "); + + if (args.length >= 2) + { + String ip = args[0]; + int port = Integer.parseInt(args[1]); + String typeName = (args.length >= 3) ? args[2].toUpperCase() : "MASTER"; // Defaults to MASTER if omitted. + ConnectionType type = ConnectionType.valueOf(typeName); + String name = (args.length >= 4) ? args[3] : "DefaultConnection"; // Defaults to DefaultConnection if omitted. + + return new ConnectionData(ip, port, type, name); + } + + return null; + } + + private static void log(String message) + { + System.out.println(String.format("[ServerManager] %s", message)); + } +} diff --git a/Plugins[Modified]/Mineplex.ServerData/src/mineplex/serverdata/servers/ServerRepository.java b/Plugins[Modified]/Mineplex.ServerData/src/mineplex/serverdata/servers/ServerRepository.java new file mode 100644 index 00000000..51f5ad8b --- /dev/null +++ b/Plugins[Modified]/Mineplex.ServerData/src/mineplex/serverdata/servers/ServerRepository.java @@ -0,0 +1,81 @@ +package mineplex.serverdata.servers; + +import java.util.Collection; +import java.util.List; + +import mineplex.serverdata.data.DedicatedServer; +import mineplex.serverdata.data.MinecraftServer; +import mineplex.serverdata.data.ServerGroup; + +/** + * The ServerRepository is used for storing/retrieving active sessions + * for {@link MinecraftServer}s, {@link DedicatedServer}s, and {@link ServerGroup}s + * from a persistent database/repoistory. + * @author Ty + * + */ +public interface ServerRepository +{ + + + /** + * @return a newly instanced snapshot {@link Collection} of all currently active + * {@link MinecraftServer}s in the repository. + */ + public Collection getServerStatuses(); + + public Collection getServerStatusesByPrefix(String prefix); + + public Collection getServersByGroup(String serverGroup); + + /** + * @param serverName - the name of the {@link MinecraftServer} to be fetched. + * @return the currently active {@link MinecraftServer} with a matching {@code serverName}, + * if an active one exists, null otherwise. + */ + public MinecraftServer getServerStatus(String serverName); + + /** + * Update (or add, if it doesn't already exist) a {@link MinecraftServer}s data + * in the repository. + * + * A {@link MinecraftServer} must be updated within {@code timeout} milliseconds before + * it expires and is removed from the repository. + * @param serverData - the {@link MinecraftServer} to add/update in the repository. + * @param timeout - the timeout (in milliseconds) before the {@link MinecraftServer} session expires. + */ + public void updataServerStatus(MinecraftServer serverData, int timeout); + + /** + * Remove an active {@link MinecraftServer} from the repository. + * @param serverData - the {@link MinecraftServer} to be removed. + */ + public void removeServerStatus(MinecraftServer serverData); + + /** + * @param serverName - the name of the server whose existence is being checked. + * @return true, if there exists an active {@link MinecraftServer} session with a + * matching {@code serverName}, false otherwise. + */ + public boolean serverExists(String serverName); + + /** + * @return a newly instanced snapshot {@link Collection} of all the + * currently active {@link DedicatedServer}s in the repository. + */ + public Collection getDedicatedServers(); + + /** + * @return a newly instanced snapshot {@link Collection} of all the + * currently active {@link ServerGroup}s in the repository. + */ + public Collection getServerGroups(Collection servers); + + public ServerGroup getServerGroup(String serverGroup); + + public Collection getDeadServers(); + + void updateServerGroup(ServerGroup serverGroup); + + public void removeServerGroup(ServerGroup serverGroup); +} diff --git a/Plugins[Original]/Mineplex.ServerData/src/mineplex/serverdata/servers/ConnectionData.java b/Plugins[Original]/Mineplex.ServerData/src/mineplex/serverdata/servers/ConnectionData.java new file mode 100644 index 00000000..e7c8676d --- /dev/null +++ b/Plugins[Original]/Mineplex.ServerData/src/mineplex/serverdata/servers/ConnectionData.java @@ -0,0 +1,54 @@ +package mineplex.serverdata.servers; + +/** + * ConnectionData stores information relevant for initiating a connection to a repository. + * @author MrTwiggy + * + */ +public class ConnectionData +{ + + public enum ConnectionType + { + MASTER, + SLAVE; + } + + private ConnectionType _type; // The type of connection available + public ConnectionType getType() { return _type; } + + private String _name; // The name associated with this connection + public String getName() { return _name; } + + private String _host; // The host URL to connect to repository + public String getHost() { return _host; } + + private int _port; // The port to connect to repository + public int getPort() { return _port; } + + /** + * Constructor + * @param host - the host URL defining the repository + * @param port - the port used for connection to repository + * @param type - the type of connection referenced by this ConnectionData + * @param name - the name associated with ConnectionData + */ + public ConnectionData(String host, int port, ConnectionType type, String name) + { + _host = host; + _port = port; + _type = type; + _name = name; + } + + /** + * @param name + * @return true, if {@code name} is null or it matches (case-insensitive) the {@code _name} associated + * with this ConnectionData, false otherwise. + */ + public boolean nameMatches(String name) + { + return (name == null || name.equalsIgnoreCase(_name)); + } +} + diff --git a/Plugins[Original]/Mineplex.ServerData/src/mineplex/serverdata/servers/DedicatedServerSorter.java b/Plugins[Original]/Mineplex.ServerData/src/mineplex/serverdata/servers/DedicatedServerSorter.java new file mode 100644 index 00000000..8f5b6853 --- /dev/null +++ b/Plugins[Original]/Mineplex.ServerData/src/mineplex/serverdata/servers/DedicatedServerSorter.java @@ -0,0 +1,20 @@ +package mineplex.serverdata.servers; + +import java.util.Comparator; + +import mineplex.serverdata.data.DedicatedServer; + +public class DedicatedServerSorter implements Comparator +{ + @Override + public int compare(DedicatedServer first, DedicatedServer second) + { + if (second.getAvailableRam() <= 1024) return -1; + else if (first.getAvailableRam() <= 1024) return 1; + else if (first.getAvailableRam() > second.getAvailableRam()) return -1; + else if (second.getAvailableRam() > first.getAvailableRam()) return 1; + else if (first.getAvailableCpu() > second.getAvailableCpu()) return -1; + else if (second.getAvailableCpu() > first.getAvailableCpu()) return 1; + else return 0; + } +} \ No newline at end of file diff --git a/Plugins[Original]/Mineplex.ServerData/src/mineplex/serverdata/servers/ServerManager.java b/Plugins[Original]/Mineplex.ServerData/src/mineplex/serverdata/servers/ServerManager.java new file mode 100644 index 00000000..20324fe1 --- /dev/null +++ b/Plugins[Original]/Mineplex.ServerData/src/mineplex/serverdata/servers/ServerManager.java @@ -0,0 +1,170 @@ +package mineplex.serverdata.servers; + +import java.io.File; +import java.nio.charset.Charset; +import java.nio.file.Files; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Random; + +import mineplex.serverdata.Region; +import mineplex.serverdata.redis.RedisConfig; +import mineplex.serverdata.redis.RedisServerRepository; +import mineplex.serverdata.servers.ConnectionData.ConnectionType; + +/** + * ServerManager handles the creation/management of {@link ServerRepository}s for use. + * @author Ty + * + */ +public class ServerManager +{ + public static final String SERVER_STATUS_LABEL = "ServerStatus"; // Label differentiating ServerStatus related servers + private static final String DEFAULT_CONFIG = "redis-config.dat"; + + // Configuration determining connection information + private static RedisConfig _config; + + // The cached repository instances + private static Map repositories = new HashMap(); + + /** + * @param host - the host url used to connect to the database + * @param port - the port to connect to the repository + * @param region - the geographical region of the {@link ServerRepository}. + * @return a newly instanced (or cached) {@link ServerRepository} for the specified {@code region}. + */ + private static ServerRepository getServerRepository(ConnectionData writeConn, ConnectionData readConn, Region region) + { + if (repositories.containsKey(region)) return repositories.get(region); + + ServerRepository repository = new RedisServerRepository(writeConn, readConn, region); + repositories.put(region, repository); + return repository; + } + + /** + * {@code host} defaults to {@value DEFAULT_REDIS_HOST} and + * {@code port} defaults to {@value DEFAULT_REDIS_PORT}. + * + * @see #getServerRepository(String, int, Region) + */ + public static ServerRepository getServerRepository(Region region) + { + return getServerRepository(getConnection(true, SERVER_STATUS_LABEL), getConnection(false, SERVER_STATUS_LABEL), region); + } + + /** + * @return the {@link ConnectionData} associated with the master instance connection. + */ + public static ConnectionData getMasterConnection() + { + return getConnection(true); + } + + /** + * Non-Deterministic: Generates random slave instance connection. + * @return the {@link ConnectionData} associated with a random slave connection. + */ + public static ConnectionData getSlaveConnection() + { + return getConnection(false); + } + + public static ConnectionData getConnection(boolean writeable, String name) + { + return getDefaultConfig().getConnection(writeable, name); + } + + /** + * @param writeable - whether the connection referenced in return can receive write-requests + * @return a newly generated {@code ConnectionData} pointing to a valid connection. + */ + public static ConnectionData getConnection(boolean writeable) + { + return getConnection(writeable, "DefaultConnection"); + } + + /** + * @return the default {@link RedisConfig} associated with this manager, providing appropriate connections. + */ + public static RedisConfig getDefaultConfig() + { + return getConfig(DEFAULT_CONFIG); + } + + /** + * @return the {@link RedisConfig} associated with this manager, providing appropriate connections. + */ + public static RedisConfig getConfig(String fileName) + { + if (_config == null) + _config = loadConfig(fileName); + + return _config; + } + + public static RedisConfig loadConfig(String fileName) + { + try + { + File configFile = new File(fileName); + + if (configFile.exists()) + { + List connections = new ArrayList(); + List lines = Files.readAllLines(configFile.toPath(), Charset.defaultCharset()); + + for (String line : lines) + { + ConnectionData connection = deserializeConnection(line); + connections.add(connection); + + } + + return new RedisConfig(connections); + } + else + { + log(fileName + " not found at " + configFile.toPath().toString()); + return new RedisConfig(); + } + } + catch (Exception exception) + { + exception.printStackTrace(); + log("---Unable To Parse Redis Configuration File---"); + } + + return null; + } + + /** + * @param line - the serialized line representing a valid {@link ConnectionData} object. + * @return a deserialized {@link ConnectionData} referenced by the {@code line} passed in. + */ + private static ConnectionData deserializeConnection(String line) + { + String[] args = line.split(" "); + + if (args.length >= 2) + { + String ip = args[0]; + int port = Integer.parseInt(args[1]); + String typeName = (args.length >= 3) ? args[2].toUpperCase() : "MASTER"; // Defaults to MASTER if omitted. + ConnectionType type = ConnectionType.valueOf(typeName); + String name = (args.length >= 4) ? args[3] : "DefaultConnection"; // Defaults to DefaultConnection if omitted. + + return new ConnectionData(ip, port, type, name); + } + + return null; + } + + private static void log(String message) + { + System.out.println(String.format("[ServerManager] %s", message)); + } +} diff --git a/Plugins[Original]/Mineplex.ServerData/src/mineplex/serverdata/servers/ServerRepository.java b/Plugins[Original]/Mineplex.ServerData/src/mineplex/serverdata/servers/ServerRepository.java new file mode 100644 index 00000000..51f5ad8b --- /dev/null +++ b/Plugins[Original]/Mineplex.ServerData/src/mineplex/serverdata/servers/ServerRepository.java @@ -0,0 +1,81 @@ +package mineplex.serverdata.servers; + +import java.util.Collection; +import java.util.List; + +import mineplex.serverdata.data.DedicatedServer; +import mineplex.serverdata.data.MinecraftServer; +import mineplex.serverdata.data.ServerGroup; + +/** + * The ServerRepository is used for storing/retrieving active sessions + * for {@link MinecraftServer}s, {@link DedicatedServer}s, and {@link ServerGroup}s + * from a persistent database/repoistory. + * @author Ty + * + */ +public interface ServerRepository +{ + + + /** + * @return a newly instanced snapshot {@link Collection} of all currently active + * {@link MinecraftServer}s in the repository. + */ + public Collection getServerStatuses(); + + public Collection getServerStatusesByPrefix(String prefix); + + public Collection getServersByGroup(String serverGroup); + + /** + * @param serverName - the name of the {@link MinecraftServer} to be fetched. + * @return the currently active {@link MinecraftServer} with a matching {@code serverName}, + * if an active one exists, null otherwise. + */ + public MinecraftServer getServerStatus(String serverName); + + /** + * Update (or add, if it doesn't already exist) a {@link MinecraftServer}s data + * in the repository. + * + * A {@link MinecraftServer} must be updated within {@code timeout} milliseconds before + * it expires and is removed from the repository. + * @param serverData - the {@link MinecraftServer} to add/update in the repository. + * @param timeout - the timeout (in milliseconds) before the {@link MinecraftServer} session expires. + */ + public void updataServerStatus(MinecraftServer serverData, int timeout); + + /** + * Remove an active {@link MinecraftServer} from the repository. + * @param serverData - the {@link MinecraftServer} to be removed. + */ + public void removeServerStatus(MinecraftServer serverData); + + /** + * @param serverName - the name of the server whose existence is being checked. + * @return true, if there exists an active {@link MinecraftServer} session with a + * matching {@code serverName}, false otherwise. + */ + public boolean serverExists(String serverName); + + /** + * @return a newly instanced snapshot {@link Collection} of all the + * currently active {@link DedicatedServer}s in the repository. + */ + public Collection getDedicatedServers(); + + /** + * @return a newly instanced snapshot {@link Collection} of all the + * currently active {@link ServerGroup}s in the repository. + */ + public Collection getServerGroups(Collection servers); + + public ServerGroup getServerGroup(String serverGroup); + + public Collection getDeadServers(); + + void updateServerGroup(ServerGroup serverGroup); + + public void removeServerGroup(ServerGroup serverGroup); +}