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
This commit is contained in:
riking 2013-12-10 15:11:09 -08:00
parent 2aec4a69ea
commit 4f273ad6b4
5 changed files with 57 additions and 27 deletions

View File

@ -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;

View File

@ -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);
}

View File

@ -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();

View File

@ -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;

View File

@ -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);
}
}
});
}