Browse Source

Fixes for importing profiles while the server is running

 - Have the active database return unloaded profiles during import (this triggers the giant warning messages)
 - Reload the users AFTER the conversion is complete, not BEFORE
riking 11 years ago
parent
commit
4f273ad6b4

+ 0 - 14
src/main/java/com/gmail/nossr50/commands/database/ConvertDatabaseCommand.java

@@ -3,13 +3,10 @@ package com.gmail.nossr50.commands.database;
 import org.bukkit.command.Command;
 import org.bukkit.command.CommandExecutor;
 import org.bukkit.command.CommandSender;
-import org.bukkit.entity.Player;
-
 import com.gmail.nossr50.mcMMO;
 import com.gmail.nossr50.database.DatabaseManager;
 import com.gmail.nossr50.database.DatabaseManagerFactory;
 import com.gmail.nossr50.datatypes.database.DatabaseType;
-import com.gmail.nossr50.datatypes.player.PlayerProfile;
 import com.gmail.nossr50.locale.LocaleLoader;
 import com.gmail.nossr50.runnables.database.DatabaseConversionTask;
 import com.gmail.nossr50.util.player.UserManager;
@@ -52,17 +49,6 @@ public class ConvertDatabaseCommand implements CommandExecutor {
                 sender.sendMessage(LocaleLoader.getString("Commands.mcconvert.Database.Start", previousType.toString(), newType.toString()));
 
                 UserManager.saveAll();
-                UserManager.clearAll();
-
-                for (Player player : mcMMO.p.getServer().getOnlinePlayers()) {
-                    PlayerProfile profile = oldDatabase.loadPlayerProfile(player.getName(), false);
-
-                    if (profile.isLoaded()) {
-                        mcMMO.getDatabaseManager().saveUser(profile);
-                    }
-
-                    UserManager.addUser(player);
-                }
 
                 new DatabaseConversionTask(oldDatabase, sender, previousType.toString(), newType.toString()).runTaskAsynchronously(mcMMO.p);
                 return true;

+ 20 - 11
src/main/java/com/gmail/nossr50/database/DatabaseManager.java

@@ -21,7 +21,8 @@ public interface DatabaseManager {
     public void purgePowerlessUsers();
 
     /**
-     * Purge users who haven't logged on in over a certain time frame from the database.
+     * Purge users who haven't logged on in over a certain time frame from the
+     * database.
      */
     public void purgeOldUsers();
 
@@ -42,13 +43,13 @@ public interface DatabaseManager {
     public boolean saveUser(PlayerProfile profile);
 
     /**
-    * Retrieve leaderboard info.
-    *
-    * @param skillName The skill to retrieve info on
-    * @param pageNumber Which page in the leaderboards to retrieve
-    * @param statsPerPage The number of stats per page
-    * @return the requested leaderboard information
-    */
+     * Retrieve leaderboard info.
+     *
+     * @param skillName The skill to retrieve info on
+     * @param pageNumber Which page in the leaderboards to retrieve
+     * @param statsPerPage The number of stats per page
+     * @return the requested leaderboard information
+     */
     public List<PlayerStat> readLeaderboard(SkillType skill, int pageNumber, int statsPerPage);
 
     /**
@@ -74,9 +75,9 @@ public interface DatabaseManager {
      *
      * @param playerName The name of the player to load from the database
      * @param createNew Whether to create a new record if the player is not
-     *          found
+     *            found
      * @return The player's data, or an unloaded PlayerProfile if not found
-     *          and createNew is false
+     *         and createNew is false
      */
     public PlayerProfile loadPlayerProfile(String playerName, boolean createNew);
 
@@ -96,9 +97,17 @@ public interface DatabaseManager {
     public void convertUsers(DatabaseManager destination);
 
     /**
-     * Retrieve the type of database in use. Custom databases should return CUSTOM.
+     * Retrieve the type of database in use. Custom databases should return
+     * CUSTOM.
      *
      * @return The type of database
      */
     public DatabaseType getDatabaseType();
+
+    /**
+     * Used for database conversion. If this is set to true, profiles may not
+     * be loaded from the database. This method will be called before and
+     * after database imports.
+     */
+    public void setLoadingDisabled(boolean state);
 }

+ 9 - 0
src/main/java/com/gmail/nossr50/database/FlatfileDatabaseManager.java

@@ -35,6 +35,7 @@ public final class FlatfileDatabaseManager implements DatabaseManager {
     private final long UPDATE_WAIT_TIME = 600000L; // 10 minutes
     private final File usersFile;
     private static final Object fileWritingLock = new Object();
+    private volatile boolean converting = false;
 
     protected FlatfileDatabaseManager() {
         usersFile = new File(mcMMO.getUsersFilePath());
@@ -42,6 +43,10 @@ public final class FlatfileDatabaseManager implements DatabaseManager {
         updateLeaderboards();
     }
 
+    public void setLoadingDisabled(boolean state) {
+        converting = state;
+    }
+
     public void purgePowerlessUsers() {
         int purgedUsers = 0;
 
@@ -369,6 +374,10 @@ public final class FlatfileDatabaseManager implements DatabaseManager {
     }
 
     public PlayerProfile loadPlayerProfile(String playerName, boolean create) {
+        if (converting) {
+            return new PlayerProfile(playerName, false);
+        }
+
         BufferedReader in = null;
         String usersFilePath = mcMMO.getUsersFilePath();
 

+ 12 - 1
src/main/java/com/gmail/nossr50/database/SQLDatabaseManager.java

@@ -49,12 +49,19 @@ public final class SQLDatabaseManager implements DatabaseManager {
     // How many connection attempts have failed
     private int reconnectAttempt = 0;
 
+    // If we're importing users, do not allow creation of profiles
+    private volatile boolean converting = false;
+
     protected SQLDatabaseManager() {
         checkStructure();
 
         new SQLDatabaseKeepaliveTask(this).runTaskTimerAsynchronously(mcMMO.p, 10, 60L * 60 * Misc.TICK_CONVERSION_FACTOR);
     }
 
+    public void setLoadingDisabled(boolean state) {
+        converting = state;
+    }
+
     public void purgePowerlessUsers() {
         if (!checkConnected()) {
             return;
@@ -346,12 +353,16 @@ public final class SQLDatabaseManager implements DatabaseManager {
     }
 
     public PlayerProfile loadPlayerProfile(String playerName, boolean create) {
+        if (converting) {
+            return new PlayerProfile(playerName, false); // return unloaded profile during database conversion
+        }
+
         return loadPlayerProfile(playerName, create, true);
     }
 
     private PlayerProfile loadPlayerProfile(String playerName, boolean create, boolean retry) {
         if (!checkConnected()) {
-            return new PlayerProfile(playerName, false); // return fake profile if not connected
+            return new PlayerProfile(playerName, false); // return unloaded profile if not connected
         }
 
         PreparedStatement statement = null;

+ 16 - 1
src/main/java/com/gmail/nossr50/runnables/database/DatabaseConversionTask.java

@@ -1,11 +1,14 @@
 package com.gmail.nossr50.runnables.database;
 
 import org.bukkit.command.CommandSender;
+import org.bukkit.entity.Player;
 import org.bukkit.scheduler.BukkitRunnable;
 
 import com.gmail.nossr50.mcMMO;
 import com.gmail.nossr50.database.DatabaseManager;
+import com.gmail.nossr50.datatypes.player.PlayerProfile;
 import com.gmail.nossr50.locale.LocaleLoader;
+import com.gmail.nossr50.util.player.UserManager;
 
 public class DatabaseConversionTask extends BukkitRunnable {
     private final DatabaseManager sourceDatabase;
@@ -20,12 +23,24 @@ public class DatabaseConversionTask extends BukkitRunnable {
 
     @Override
     public void run() {
-        sourceDatabase.convertUsers(mcMMO.getDatabaseManager());
+        try {
+            sourceDatabase.setLoadingDisabled(true);
+            sourceDatabase.convertUsers(mcMMO.getDatabaseManager());
+        }
+        finally {
+            sourceDatabase.setLoadingDisabled(false);
+        }
 
         mcMMO.p.getServer().getScheduler().runTask(mcMMO.p, new Runnable() {
             @Override
             public void run() {
                 sender.sendMessage(message);
+
+                // Reload all users from the new database
+                UserManager.clearAll();
+                for (Player player : mcMMO.p.getServer().getOnlinePlayers()) {
+                    UserManager.addUser(player);
+                }
             }
         });
    }