Skip to content

Commit

Permalink
Fixed migration stuff and now it works just fine
Browse files Browse the repository at this point in the history
  • Loading branch information
Lauriichan committed Feb 4, 2022
1 parent 64d4e7e commit f74b022
Show file tree
Hide file tree
Showing 19 changed files with 236 additions and 149 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package me.lauriichan.minecraft.wildcard.core;

import com.syntaxphoenix.syntaxapi.logging.ILogger;

import me.lauriichan.minecraft.wildcard.core.settings.PluginSettings;
import me.lauriichan.minecraft.wildcard.core.util.Singleton;

public final class Wildcard {

private Wildcard() {
throw new UnsupportedOperationException("Constant provider");
}

public static boolean isDebug() {
return Singleton.get(PluginSettings.class).getBoolean("debug", false);
}

public static ILogger getLogger() {
return Singleton.get(ILogger.class);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -57,14 +57,13 @@ public final class WildcardCore {

private final Container<ClassLookupProvider> classProvider = Container.of();
private final Container<Injections> injections = Container.of();


public WildcardCore(final IWildcardPlugin plugin) {
this.plugin = plugin;
this.logger = new JavaLogger(plugin.getAdapter());
this.componentParser = new PlatformComponentParser(plugin.getAdapter().getComponentAdapter());
Singleton.inject(this);
Singleton.inject(logger);
this.componentParser = new PlatformComponentParser(plugin.getAdapter().getComponentAdapter());
this.eventManager = new EventManager(logger);
eventManager.registerEvents(new PathListener());
eventManager.registerEvents(new CommandListener());
Expand Down Expand Up @@ -119,7 +118,7 @@ public void preSetup() {
classProvider.replace(new ClassLookupProvider());
injections.replace(new Injections(classProvider.get())).get().setup();
}

public void registerCommands() {
register(new WildcardCommand());
}
Expand Down Expand Up @@ -216,7 +215,7 @@ public IWildcardPlugin getPlugin() {
public EventManager getEventManager() {
return eventManager;
}

public PlatformComponentParser getComponentParser() {
return componentParser;
}
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
import com.syntaxphoenix.syntaxapi.logging.LogTypeId;
import com.syntaxphoenix.syntaxapi.reflection.ClassCache;

import me.lauriichan.minecraft.wildcard.core.Wildcard;
import me.lauriichan.minecraft.wildcard.core.util.DynamicArray;
import me.lauriichan.minecraft.wildcard.core.util.InstanceCreator;
import me.lauriichan.minecraft.wildcard.core.util.ReflectHelper;
Expand All @@ -20,6 +21,7 @@
import me.lauriichan.minecraft.wildcard.migration.IMigrationManager;
import me.lauriichan.minecraft.wildcard.migration.IMigrationSource;
import me.lauriichan.minecraft.wildcard.migration.Migration;
import me.lauriichan.minecraft.wildcard.migration.MigrationProcessor;
import me.lauriichan.minecraft.wildcard.migration.MigrationProvider;
import me.lauriichan.minecraft.wildcard.migration.MigrationTarget;
import me.lauriichan.minecraft.wildcard.migration.MigrationType;
Expand All @@ -30,16 +32,19 @@ public final class MigrationManager implements IMigrationManager {
private final Registry<Class<?>, MigrationType<?, ?>> types = new Registry<>();

public MigrationManager() {
ILogger logger = Singleton.get(ILogger.class);
try (BufferedReader reader = PathSource.ofResource("META-INF/migrations").openReader()) {
ILogger logger = Wildcard.getLogger();
try (BufferedReader reader = PathSource.ofResource(MigrationProcessor.MIGRATION_RESOURCE).openReader()) {
String line;
while ((line = reader.readLine()) != null) {
if(line == null || line.trim().isEmpty()) {
continue;
}
Class<?> clazz = ClassCache.getClass(line);
if (clazz == null) {
logger.log(LogTypeId.WARNING, "Couldn't find migration class '" + line + "'!");
continue;
}
if (MigrationProvider.class.isAssignableFrom(clazz)) {
if (!MigrationProvider.class.isAssignableFrom(clazz)) {
logger.log(LogTypeId.WARNING, "Migration class '" + clazz.getSimpleName() + "' is not a MigrationProvider!");
continue;
}
Expand Down Expand Up @@ -87,8 +92,7 @@ public MigrationManager() {
migrations.add(new MigrationTarget<>(migration, provider));
}
} catch (IOException exp) {
logger.log(LogTypeId.ERROR, "Failed to load migrations!");
logger.log(LogTypeId.ERROR, exp);
throw new IllegalStateException("Failed to load migrations!", exp);
}
}

Expand All @@ -101,7 +105,7 @@ public MigrationManager() {
try {
migrationType = InstanceCreator.create(type, Singleton.getInjects());
} catch (Exception e) {
ILogger logger = Singleton.get(ILogger.class);
ILogger logger = Wildcard.getLogger();
logger.log(LogTypeId.WARNING, "Failed to create instance of migration type '" + type.getSimpleName() + "'!");
logger.log(LogTypeId.WARNING, e);
return null;
Expand Down Expand Up @@ -133,7 +137,7 @@ public <M extends MigrationProvider> List<MigrationTarget<M>> getTargets(Class<M
if (migration == null) {
throw new IllegalStateException("Can't find migration type '" + type.getSimpleName() + "'!");
}
if (migration.getSource().isAssignableFrom(source.getClass())) {
if (!migration.getSource().isAssignableFrom(source.getClass())) {
throw new IllegalArgumentException("migration source '" + source.getClass().getSimpleName()
+ "' is not compatible with migration type '" + type.getSimpleName() + "'!");
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package me.lauriichan.minecraft.wildcard.core.data.migration.impl;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

Expand All @@ -23,10 +24,14 @@ public final SQLTable getTable() {

public abstract String getNewFormat();

public abstract String getLimit(long offset, long limit);

public abstract String getFormat(ResultSet set) throws SQLException;

public abstract ResultSet requestTableSql(String table, Connection connection) throws SQLException;

public abstract void migrateBatch(ResultSet legacyData, Connection connection, String table) throws SQLException;
public abstract PreparedStatement startBatch(Connection connection, String table) throws SQLException;

public abstract void migrateBatch(PreparedStatement statement, ResultSet entry) throws SQLException;

}
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,12 @@
import java.util.Collections;
import java.util.EnumMap;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.function.Function;

import com.syntaxphoenix.syntaxapi.logging.ILogger;
import com.syntaxphoenix.syntaxapi.logging.LogTypeId;

import me.lauriichan.minecraft.wildcard.core.Wildcard;
import me.lauriichan.minecraft.wildcard.core.data.migration.impl.SQLMigration;
import me.lauriichan.minecraft.wildcard.core.data.storage.SQLDatabase;
import me.lauriichan.minecraft.wildcard.core.data.storage.SQLTable;
Expand All @@ -24,9 +24,12 @@

public final class SQLMigrationType extends MigrationType<SQLDatabase, SQLMigration> {

private static final long ROW_LIMIT = 500;

private static final String CREATE_TABLE = "CREATE TABLE %s(%s)";
private static final String RENAME_TABLE = "ALTER TABLE %s RENAME TO %s";
private static final String SELECT_TABLE = "SELECT * FROM %s LIMIT 100";
private static final String SELECT_TABLE = "SELECT * FROM %s ";
private static final String DROP_TABLE = "DROP TABLE %s";

private static final Function<SQLTable, ArrayList<SQLMigration>> BUILDER = (i) -> new ArrayList<>();

Expand Down Expand Up @@ -58,51 +61,53 @@ public void migrate(IMigrationManager manager, SQLDatabase source) throws Except
return;
}
ILogger logger = Singleton.get(ILogger.class);
ArrayList<CompletableFuture<Void>> tasks = new ArrayList<>();
for (SQLTable table : SQLTable.values()) {
tasks.add(CompletableFuture.runAsync(() -> {
if (!tableMigrations.containsKey(table)) {
if (!tableMigrations.containsKey(table)) {
return;
}
ArrayList<SQLMigration> migrations = tableMigrations.get(table);
if (migrations.isEmpty()) {
return; // How?
}
Collections.sort(migrations);
SQLMigration first = migrations.get(0);
try (Connection connection = source.getConnection()) {
State state = getFormatState(first, source.getTableName(table), first.getOldFormat(), connection);
switch (state) {
case LEGACY:
break;
case NOT_AVAILABLE:
PreparedStatement statement = connection
.prepareStatement(String.format(CREATE_TABLE, source.getTableName(table), first.getNewFormat()));
statement.closeOnCompletion();
statement.executeUpdate();
default: // We're up2date, no migration required
return;
}
ArrayList<SQLMigration> migrations = tableMigrations.get(table);
if (migrations.isEmpty()) {
return; // How?
}
Collections.sort(migrations);
SQLMigration first = migrations.get(0);
try (Connection connection = source.getConnection()) {
State state = getFormatState(first, source.getTableName(table), first.getOldFormat(), connection);
switch (state) {
case LEGACY:
break;
case NOT_AVAILABLE:
connection.prepareStatement(String.format(CREATE_TABLE, table, first.getNewFormat())).executeUpdate();
default: // We're up2date, no migration required
return;
logger.log(LogTypeId.WARNING, "Table '" + source.getTableName(table) + "' has an old format, migrating...");
// We're not up2date so we check for the oldest version which is compatible
boolean migrate = false;
for (int i = migrations.size() - 1; i >= 0; i--) {
SQLMigration migration = migrations.get(i);
if (getFormatState(migration, source.getTableName(table), migration.getOldFormat(), connection) == State.UP2DATE) {
migrate = true; // Now we know which version is the oldest and can start to migrate to newer ones
continue;
}
// We're not up2date so we check for the oldest version which is compatbile
boolean migrate = false;
for (int i = migrations.size() - 1; i >= 0; i--) {
SQLMigration migration = migrations.get(i);
if (getFormatState(migration, source.getTableName(table), migration.getOldFormat(), connection) == State.UP2DATE) {
migrate = true; // Now we know which version is the oldest and can start to migrate to newer ones
continue;
}
if (!migrate) {
continue;
}
if (!applyMigration(logger, connection, source, migration)) {
break;
if (!migrate) {
if (i == 0) { // Force migrate oldest migration
i = migrations.size();
migrate = true;
}
continue;
}
if (!applyMigration(logger, connection, source, migration)) {
throw new IllegalStateException("Failed to migrate database '" + source.getClass().getSimpleName() + "'!");
}
} catch (SQLException e) {
logger.log(LogTypeId.ERROR, "Failed to migrate table '" + table + "'");
logger.log(LogTypeId.ERROR, e);
}
}));
}
for (int i = 0; i < tasks.size(); i++) {
tasks.get(i).join(); // Await all tasks until completion
} catch (SQLException e) {
logger.log(LogTypeId.ERROR, "Failed to migrate table '" + source.getTableName(table) + "'");
logger.log(LogTypeId.ERROR, e);
}
}
}

Expand All @@ -111,35 +116,61 @@ private boolean applyMigration(ILogger logger, Connection connection, SQLDatabas
final String oldFormat = migration.getOldFormat();
final String newFormat = migration.getNewFormat();
final String tableLegacy = table + "_LEGACY";
logger.log(LogTypeId.WARNING, "Table '" + table + "' has an old format, migrating...");
// Rename table
PreparedStatement statement = connection.prepareStatement(String.format(RENAME_TABLE, table, tableLegacy));
statement.executeUpdate();
statement.execute();
statement.close();
// Create new table
statement = connection.prepareStatement(String.format(CREATE_TABLE, table, newFormat));
statement.executeUpdate();
// Request table data
final String selectLegacyTable = String.format(SELECT_TABLE, tableLegacy);
try {
statement = connection.prepareStatement(SELECT_TABLE, ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_UPDATABLE);
logger.log(LogTypeId.INFO, "[" + migration.getId() + "] Migrated 0 entries of Table '" + table + "'...");
long amount = 0;
PreparedStatement batch = migration.startBatch(connection, table);
while (true) {
statement = connection.prepareStatement(selectLegacyTable + migration.getLimit(amount, ROW_LIMIT));
statement.closeOnCompletion();
ResultSet set = statement.executeQuery();
if (!set.next()) {
break;
}
set.beforeFirst();
migration.migrateBatch(set, connection, table);
set.beforeFirst();
int next = 0;
batch.clearBatch();
while (set.next()) {
set.deleteRow();
migration.migrateBatch(batch, set);
next++;
}
if(!set.isClosed()) {
set.close();
}
if (next == 0) {
batch.close();
break;
}
batch.executeBatch();
amount += next;
logger.log(LogTypeId.INFO, "[" + migration.getId() + "] Migrated " + amount + " entries of Table '" + table + "'...");
}
logger.log(LogTypeId.INFO, "[" + migration.getId() + "] Migrated a total of " + amount + " entries of Table '" + table + "'!");
} catch (SQLException exp) {
logger.log(LogTypeId.ERROR,
"Failed to migrate table '" + table + "' to from (" + oldFormat + ") to (" + newFormat + ") [" + migration.getId() + "]");
"Failed to migrate table '" + table + "' from (" + oldFormat + ") to (" + newFormat + ") [" + migration.getId() + "]");
logger.log(LogTypeId.ERROR, exp);
return false;
}
logger.log(LogTypeId.WARNING, "Migration of Table '" + table + "' was done successfully");
logger.log(LogTypeId.WARNING, "[" + migration.getId() + "] Migration of Table '" + table + "' was done successfully");
logger.log(LogTypeId.WARNING, "[" + migration.getId() + "] Dropping old table '" + tableLegacy + "'!");
try {
statement = connection.prepareStatement(String.format(DROP_TABLE, tableLegacy));
statement.execute();
statement.close();
} catch (SQLException exp) {
logger.log(LogTypeId.WARNING, "[" + migration.getId() + "] Failed to drop old table '" + tableLegacy + "'!");
if (Wildcard.isDebug()) {
logger.log(LogTypeId.DEBUG, exp);
}
return true;
}
logger.log(LogTypeId.WARNING, "[" + migration.getId() + "] Old table '" + tableLegacy + "' dropped successfully!");
return true;
}

Expand All @@ -149,14 +180,17 @@ private final State getFormatState(SQLMigration migration, String table, String
return State.NOT_AVAILABLE;
}
String format = extractFormat(migration.getFormat(set));
if(!set.isClosed()) {
set.close();
}
if (format.equals(oldFormat)) {
return State.LEGACY;
}
return State.UP2DATE;
}

private String extractFormat(String input) {
return (input = input.split("(", 2)[1]).substring(0, input.length() - 1);
return (input = input.split("\\(", 2)[1]).substring(0, input.length() - 1);
}

private static enum State {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
public abstract class MySQLMigration extends SQLMigration {

private static final String SELECT_TABLE = "SHOW CREATE TABLE %s";
private static final String LIMIT_FORMAT = "LIMIT %s, %s";

public MySQLMigration(SQLTable table) {
super(table);
Expand All @@ -24,5 +25,10 @@ public ResultSet requestTableSql(String table, Connection connection) throws SQL
public String getFormat(ResultSet set) throws SQLException {
return set.getString(2);
}

@Override
public String getLimit(long offset, long limit) {
return String.format(LIMIT_FORMAT, offset, limit);
}

}
Loading

0 comments on commit f74b022

Please sign in to comment.