diff --git a/src/main/java/ch/njol/skript/variables/FlatFileStorage.java b/src/main/java/ch/njol/skript/variables/FlatFileStorage.java index c9dadeb265b..e18ef041d71 100644 --- a/src/main/java/ch/njol/skript/variables/FlatFileStorage.java +++ b/src/main/java/ch/njol/skript/variables/FlatFileStorage.java @@ -126,10 +126,10 @@ public class FlatFileStorage extends VariablesStorage { /** * Create a new CSV storage of the given name. * - * @param name the name. + * @param type the databse type i.e. CSV. */ - FlatFileStorage(String name) { - super(name); + FlatFileStorage(String type) { + super(type); } /** @@ -439,7 +439,7 @@ public final void saveVariables(boolean finalSave) { pw.close(); FileUtils.move(tempFile, file, true); } catch (IOException e) { - Skript.error("Unable to make a final save of the database '" + databaseName + + Skript.error("Unable to make a final save of the database '" + getUserConfigurationName() + "' (no variables are lost): " + ExceptionUtils.toString(e)); // FIXME happens at random - check locks/threads } diff --git a/src/main/java/ch/njol/skript/variables/MySQLStorage.java b/src/main/java/ch/njol/skript/variables/MySQLStorage.java index d81594c3bc7..884529388ab 100644 --- a/src/main/java/ch/njol/skript/variables/MySQLStorage.java +++ b/src/main/java/ch/njol/skript/variables/MySQLStorage.java @@ -25,8 +25,8 @@ public class MySQLStorage extends SQLStorage { - MySQLStorage(String name) { - super(name, "CREATE TABLE IF NOT EXISTS %s (" + + MySQLStorage(String type) { + super(type, "CREATE TABLE IF NOT EXISTS %s (" + "rowid BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY," + "name VARCHAR(" + MAX_VARIABLE_NAME_LENGTH + ") NOT NULL UNIQUE," + "type VARCHAR(" + MAX_CLASS_CODENAME_LENGTH + ")," + diff --git a/src/main/java/ch/njol/skript/variables/SQLStorage.java b/src/main/java/ch/njol/skript/variables/SQLStorage.java index 6dce0d4910a..496d6b98bef 100644 --- a/src/main/java/ch/njol/skript/variables/SQLStorage.java +++ b/src/main/java/ch/njol/skript/variables/SQLStorage.java @@ -79,11 +79,11 @@ public abstract class SQLStorage extends VariablesStorage { /** * Creates a SQLStorage with a create table query. * - * @param name The name to be sent through this constructor when newInstance creates this class. + * @param type The database type i.e. CSV. * @param createTableQuery The create table query to send to the SQL engine. */ - public SQLStorage(String name, String createTableQuery) { - super(name); + public SQLStorage(String type, String createTableQuery) { + super(type); this.createTableQuery = createTableQuery; this.tableName = "variables21"; } @@ -160,14 +160,14 @@ protected boolean load_i(SectionNode n) { final boolean hadNewTable = db.isTable(getTableName()); if (getFormattedCreateQuery() == null){ - Skript.error("Could not create the variables table in the database. The query to create the variables table '" + tableName + "' in the database '" + databaseName + "' is null."); + Skript.error("Could not create the variables table in the database. The query to create the variables table '" + tableName + "' in the database '" + getUserConfigurationName() + "' is null."); return false; } try { db.query(getFormattedCreateQuery()); } catch (final SQLException e) { - Skript.error("Could not create the variables table '" + tableName + "' in the database '" + databaseName + "': " + e.getLocalizedMessage() + ". " + Skript.error("Could not create the variables table '" + tableName + "' in the database '" + getUserConfigurationName() + "': " + e.getLocalizedMessage() + ". " + "Please create the table yourself using the following query: " + String.format(createTableQuery, tableName).replace(",", ", ").replaceAll("\\s+", " ")); return false; } @@ -200,7 +200,7 @@ protected boolean load_i(SectionNode n) { // store old variables in new table and delete the old table if (hasOldTable) { if (!hadNewTable) { - Skript.info("[2.1] Updating the database '" + databaseName + "' to the new format..."); + Skript.info("[2.1] Updating the database '" + getUserConfigurationName() + "' to the new format..."); try { Variables.getReadLock().lock(); for (final Entry v : Variables.getVariablesHashMap().entrySet()) { @@ -221,7 +221,7 @@ protected boolean load_i(SectionNode n) { final ResultSet r = db.query("SELECT * FROM " + OLD_TABLE_NAME + " LIMIT 1"); try { if (r.next()) {// i.e. the old table is not empty - Skript.error("Could not successfully convert & transfer all variables to the new table in the database '" + databaseName + "'. " + Skript.error("Could not successfully convert & transfer all variables to the new table in the database '" + getUserConfigurationName() + "'. " + "Variables that could not be transferred are left in the old table and Skript will reattempt to transfer them whenever it starts until the old table is empty or is manually deleted. " + "Please note that variables recreated by scripts will count as converted and will be removed from the old table on the next restart."); } else { @@ -231,13 +231,13 @@ protected boolean load_i(SectionNode n) { connect(); db.query("DROP TABLE " + OLD_TABLE_NAME); } catch (final SQLException e) { - Skript.error("There was an error deleting the old variables table from the database '" + databaseName + "', please delete it yourself: " + e.getLocalizedMessage()); + Skript.error("There was an error deleting the old variables table from the database '" + getUserConfigurationName() + "', please delete it yourself: " + e.getLocalizedMessage()); error = true; } if (!error) - Skript.info("Successfully deleted the old variables table from the database '" + databaseName + "'."); + Skript.info("Successfully deleted the old variables table from the database '" + getUserConfigurationName() + "'."); if (!hadNewTable) - Skript.info("Database '" + databaseName + "' successfully updated."); + Skript.info("Database '" + getUserConfigurationName() + "' successfully updated."); } } finally { r.close(); @@ -265,7 +265,7 @@ public void run() { } catch (final InterruptedException e) {} } } - }, "Skript database '" + databaseName + "' connection keep-alive thread").start(); + }, "Skript database '" + getUserConfigurationName() + "' connection keep-alive thread").start(); return true; } @@ -273,7 +273,7 @@ public void run() { @Override protected void allLoaded() { - Skript.debug("Database " + databaseName + " loaded. Queue size = " + changesQueue.size()); + Skript.debug("Database " + getUserConfigurationName() + " loaded. Queue size = " + changesQueue.size()); // start committing thread. Its first execution will also commit the first batch of changed variables. Skript.newThread(new Runnable() { @@ -296,7 +296,7 @@ public void run() { } catch (final InterruptedException e) {} } } - }, "Skript database '" + databaseName + "' transaction committing thread").start(); + }, "Skript database '" + getUserConfigurationName() + "' transaction committing thread").start(); if (monitor) { Skript.newThread(new Runnable() { @@ -327,7 +327,7 @@ public void run() { } } } - }, "Skript database '" + databaseName + "' monitor thread").start(); + }, "Skript database '" + getUserConfigurationName() + "' monitor thread").start(); } } @@ -352,9 +352,9 @@ private final boolean connect(final boolean first) { final Database db = this.db.get(); if (db == null || !db.open()) { if (first) - Skript.error("Cannot connect to the database '" + databaseName + "'! Please make sure that all settings are correct");// + (type == Type.MYSQL ? " and that the database software is running" : "") + "."); + Skript.error("Cannot connect to the database '" + getUserConfigurationName() + "'! Please make sure that all settings are correct");// + (type == Type.MYSQL ? " and that the database software is running" : "") + "."); else - Skript.exception("Cannot reconnect to the database '" + databaseName + "'!"); + Skript.exception("Cannot reconnect to the database '" + getUserConfigurationName() + "'!"); return false; } try { @@ -400,7 +400,7 @@ private boolean prepareQueries() { } catch (final SQLException e) {} monitorCleanUpQuery = db.prepare("DELETE FROM " + getTableName() + " WHERE value IS NULL AND rowid < ?"); } catch (final SQLException e) { - Skript.exception(e, "Could not prepare queries for the database '" + databaseName + "': " + e.getLocalizedMessage()); + Skript.exception(e, "Could not prepare queries for the database '" + getUserConfigurationName() + "': " + e.getLocalizedMessage()); return false; } } @@ -577,7 +577,7 @@ public SQLException call() throws Exception { int i = 1; final String name = r.getString(i++); if (name == null) { - Skript.error("Variable with NULL name found in the database '" + databaseName + "', ignoring it"); + Skript.error("Variable with NULL name found in the database '" + getUserConfigurationName() + "', ignoring it"); continue; } final String type = r.getString(i++); @@ -590,7 +590,7 @@ public SQLException call() throws Exception { @SuppressWarnings("unused") Serializer s; if (c == null || (s = c.getSerializer()) == null) { - Skript.error("Cannot load the variable {" + name + "} from the database '" + databaseName + "', because the type '" + type + "' cannot be recognised or cannot be stored in variables"); + Skript.error("Cannot load the variable {" + name + "} from the database '" + getUserConfigurationName() + "', because the type '" + type + "' cannot be recognised or cannot be stored in variables"); continue; } // if (s.mustSyncDeserialization()) { @@ -598,7 +598,7 @@ public SQLException call() throws Exception { // } else { final Object d = Classes.deserialize(c, value); if (d == null) { - Skript.error("Cannot load the variable {" + name + "} from the database '" + databaseName + "', because it cannot be loaded as " + c.getName().withIndefiniteArticle()); + Skript.error("Cannot load the variable {" + name + "} from the database '" + getUserConfigurationName() + "', because it cannot be loaded as " + c.getName().withIndefiniteArticle()); continue; } Variables.variableLoaded(name, d, SQLStorage.this); @@ -623,7 +623,7 @@ public SQLException call() throws Exception { // for (final VariableInfo o : syncDeserializing) { // final Object d = Classes.deserialize(o.ci, o.value); // if (d == null) { -// Skript.error("Cannot load the variable {" + o.name + "} from the database " + databaseName + ", because it cannot be loaded as a " + o.ci.getName()); +// Skript.error("Cannot load the variable {" + o.name + "} from the database " + getUserConfigurationName() + ", because it cannot be loaded as a " + o.ci.getName()); // continue; // } // Variables.variableLoaded(o.name, d, DatabaseStorage.this); @@ -655,7 +655,7 @@ public SQLException call() throws Exception { private void oldLoadVariables(final ResultSet r, final boolean hadNewTable) throws SQLException { // synchronized (oldSyncDeserializing) { - final VariablesStorage temp = new VariablesStorage(databaseName + " old variables table") { + final VariablesStorage temp = new VariablesStorage(getUserConfigurationName() + " old variables table") { @Override protected boolean save(final String name, @Nullable final String type, @Nullable final byte[] value) { assert type == null : name + "; " + type; diff --git a/src/main/java/ch/njol/skript/variables/SQLiteStorage.java b/src/main/java/ch/njol/skript/variables/SQLiteStorage.java index fc4c54072d6..bb52883eba0 100644 --- a/src/main/java/ch/njol/skript/variables/SQLiteStorage.java +++ b/src/main/java/ch/njol/skript/variables/SQLiteStorage.java @@ -27,8 +27,8 @@ public class SQLiteStorage extends SQLStorage { - SQLiteStorage(String name) { - super(name, "CREATE TABLE IF NOT EXISTS %s (" + + SQLiteStorage(String type) { + super(type, "CREATE TABLE IF NOT EXISTS %s (" + "name VARCHAR(" + MAX_VARIABLE_NAME_LENGTH + ") NOT NULL PRIMARY KEY," + "type VARCHAR(" + MAX_CLASS_CODENAME_LENGTH + ")," + "value BLOB(" + MAX_VALUE_SIZE + ")," + diff --git a/src/main/java/ch/njol/skript/variables/Variables.java b/src/main/java/ch/njol/skript/variables/Variables.java index 8bdca7e77bd..8f476ae8eee 100644 --- a/src/main/java/ch/njol/skript/variables/Variables.java +++ b/src/main/java/ch/njol/skript/variables/Variables.java @@ -244,7 +244,7 @@ public static boolean load() { constructor.setAccessible(true); variablesStorage = (VariablesStorage) constructor.newInstance(type); } catch (InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException | NoSuchMethodException | SecurityException e) { - Skript.error("Failed to initalize database type '" + type + "'"); + Skript.error("Failed to initialize database `" + name + "`"); successful = false; continue; } @@ -745,8 +745,8 @@ static boolean variableLoaded(String name, @Nullable Object value, VariablesStor // Warn if needed if (loadConflicts <= MAX_CONFLICT_WARNINGS) { Skript.warning("The variable {" + name + "} was loaded twice from different databases (" + - existingVariableStorage.databaseName + " and " + source.databaseName + - "), only the one from " + source.databaseName + " will be kept."); + existingVariableStorage.getUserConfigurationName() + " and " + source.getUserConfigurationName() + + "), only the one from " + source.getUserConfigurationName() + " will be kept."); } else if (loadConflicts == MAX_CONFLICT_WARNINGS + 1) { Skript.warning("[!] More than " + MAX_CONFLICT_WARNINGS + " variables were loaded more than once from different databases, " + diff --git a/src/main/java/ch/njol/skript/variables/VariablesStorage.java b/src/main/java/ch/njol/skript/variables/VariablesStorage.java index d130ec83b2a..a9ac1f8129d 100644 --- a/src/main/java/ch/njol/skript/variables/VariablesStorage.java +++ b/src/main/java/ch/njol/skript/variables/VariablesStorage.java @@ -20,6 +20,9 @@ import java.io.File; import java.io.IOException; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.Set; import java.util.concurrent.LinkedBlockingQueue; import java.util.regex.Pattern; import java.util.regex.PatternSyntaxException; @@ -68,9 +71,14 @@ public abstract class VariablesStorage implements Closeable { protected volatile boolean closed = false; /** - * The name of the database, i.e. this storage. + * The name of the database */ - protected final String databaseName; + private String databaseName; + + /** + * The type of the database, i.e. CSV. + */ + private final String databaseType; /** * The file associated with this variable storage. @@ -98,11 +106,11 @@ public abstract class VariablesStorage implements Closeable { * This will also create the {@link #writeThread}, but it must be started * with {@link #load(SectionNode)}. * - * @param name the name. + * @param type the database type i.e. CSV. */ - protected VariablesStorage(String name) { - assert name != null; - databaseName = name; + protected VariablesStorage(String type) { + assert type != null; + databaseType = type; writeThread = Skript.newThread(() -> { while (!closed) { @@ -120,7 +128,29 @@ protected VariablesStorage(String name) { // Ignored as the `closed` field will indicate whether the thread actually needs to stop } } - }, "Skript variable save thread for database '" + name + "'"); + }, "Skript variable save thread for database '" + type + "'"); + } + + /** + * Get the config name of a database + *

+ * Note: Returns the user set name for the database, ex: + *

{@code
+	 * default: <- Config Name
+	 *    type: CSV
+	 * }
+ * @return name of database + */ + protected final String getUserConfigurationName() { + return databaseName; + } + + /** + * Get the config type of a database + * @return type of databse + */ + protected final String getDatabaseType() { + return databaseType; } /** @@ -170,6 +200,8 @@ protected T getValue(SectionNode sectionNode, String key, Class type) { } } + private static final Set registeredFiles = new HashSet<>(); + /** * Loads the configuration for this variable storage * from the given section node. @@ -178,6 +210,8 @@ protected T getValue(SectionNode sectionNode, String key, Class type) { * @return whether the loading succeeded. */ public final boolean load(SectionNode sectionNode) { + databaseName = sectionNode.getKey(); + String pattern = getValue(sectionNode, "pattern"); if (pattern == null) return false; @@ -222,6 +256,12 @@ public final boolean load(SectionNode sectionNode) { return false; } + if (registeredFiles.contains(file)) { + Skript.error("Database `" + databaseName + "` failed to load. The file `" + fileName + "` is already registered to another database."); + return false; + } + registeredFiles.add(file); + // Set the backup interval, if present & enabled if (!"0".equals(getValue(sectionNode, "backup interval"))) { Timespan backupInterval = getValue(sectionNode, "backup interval", Timespan.class);