Better flatfile purge performance; sync flatdb access ...

... to avoid data loss
This commit is contained in:
riking 2013-06-23 11:45:30 -07:00
parent c967a327c6
commit c588fe7420

View File

@ -13,6 +13,7 @@ import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import org.bukkit.Bukkit;
import org.bukkit.OfflinePlayer; import org.bukkit.OfflinePlayer;
import com.gmail.nossr50.mcMMO; import com.gmail.nossr50.mcMMO;
@ -32,6 +33,7 @@ public final class FlatfileDatabaseManager implements DatabaseManager {
private final long UPDATE_WAIT_TIME = 600000L; // 10 minutes private final long UPDATE_WAIT_TIME = 600000L; // 10 minutes
private final File usersFile; private final File usersFile;
private static final Object fileWritingLock = new Object();
protected FlatfileDatabaseManager() { protected FlatfileDatabaseManager() {
usersFile = new File(mcMMO.getUsersFilePath()); usersFile = new File(mcMMO.getUsersFilePath());
@ -48,9 +50,8 @@ public final class FlatfileDatabaseManager implements DatabaseManager {
FileWriter out = null; FileWriter out = null;
String usersFilePath = mcMMO.getUsersFilePath(); String usersFilePath = mcMMO.getUsersFilePath();
// Rationale for doing a file read instead of using the cached values: // This code is O(n) instead of O(n²)
// If mulitple users need be removed, this only opens the file once as synchronized (fileWritingLock) {
// opposed to calling removeUser which opens the file once each time.
try { try {
in = new BufferedReader(new FileReader(usersFilePath)); in = new BufferedReader(new FileReader(usersFilePath));
StringBuilder writer = new StringBuilder(); StringBuilder writer = new StringBuilder();
@ -110,6 +111,7 @@ public final class FlatfileDatabaseManager implements DatabaseManager {
} }
} }
} }
}
mcMMO.p.getLogger().info("Purged " + purgedUsers + " users from the database."); mcMMO.p.getLogger().info("Purged " + purgedUsers + " users from the database.");
} }
@ -120,9 +122,61 @@ public final class FlatfileDatabaseManager implements DatabaseManager {
mcMMO.p.getLogger().info("Purging old users..."); mcMMO.p.getLogger().info("Purging old users...");
for (OfflinePlayer player : mcMMO.p.getServer().getOfflinePlayers()) {
if (!player.isOnline() && (currentTime - player.getLastPlayed() > PURGE_TIME && removeUser(player.getName()))) { BufferedReader in = null;
FileWriter out = null;
String usersFilePath = mcMMO.getUsersFilePath();
// This code is O(n) instead of O(n²)
synchronized (fileWritingLock) {
try {
in = new BufferedReader(new FileReader(usersFilePath));
StringBuilder writer = new StringBuilder();
String line = "";
while ((line = in.readLine()) != null) {
String[] character = line.split(":");
String name = character[0];
OfflinePlayer player = Bukkit.getOfflinePlayer(name);
boolean old = true;
if (player != null) {
old = (currentTime - player.getLastPlayed()) > PURGE_TIME;
}
if (!old) {
writer.append(line);
}
else {
removedPlayers++; removedPlayers++;
Misc.profileCleanup(name);
}
}
// Write the new file
out = new FileWriter(usersFilePath);
out.write(writer.toString());
}
catch (IOException e) {
mcMMO.p.getLogger().severe("Exception while reading " + usersFilePath + " (Are you sure you formatted it correctly?)" + e.toString());
}
finally {
if (in != null) {
try {
in.close();
}
catch (IOException ex) {
ex.printStackTrace();
}
}
if (out != null) {
try {
out.close();
}
catch (IOException ex) {
ex.printStackTrace();
}
}
} }
} }
@ -136,6 +190,7 @@ public final class FlatfileDatabaseManager implements DatabaseManager {
FileWriter out = null; FileWriter out = null;
String usersFilePath = mcMMO.getUsersFilePath(); String usersFilePath = mcMMO.getUsersFilePath();
synchronized (fileWritingLock) {
try { try {
in = new BufferedReader(new FileReader(usersFilePath)); in = new BufferedReader(new FileReader(usersFilePath));
StringBuilder writer = new StringBuilder(); StringBuilder writer = new StringBuilder();
@ -177,6 +232,7 @@ public final class FlatfileDatabaseManager implements DatabaseManager {
} }
} }
} }
}
Misc.profileCleanup(playerName); Misc.profileCleanup(playerName);
@ -190,6 +246,7 @@ public final class FlatfileDatabaseManager implements DatabaseManager {
FileWriter out = null; FileWriter out = null;
String usersFilePath = mcMMO.getUsersFilePath(); String usersFilePath = mcMMO.getUsersFilePath();
synchronized (fileWritingLock) {
try { try {
// Open the file // Open the file
in = new BufferedReader(new FileReader(usersFilePath)); in = new BufferedReader(new FileReader(usersFilePath));
@ -276,6 +333,7 @@ public final class FlatfileDatabaseManager implements DatabaseManager {
} }
} }
} }
}
public List<PlayerStat> readLeaderboard(String skillName, int pageNumber, int statsPerPage) { public List<PlayerStat> readLeaderboard(String skillName, int pageNumber, int statsPerPage) {
updateLeaderboards(); updateLeaderboards();
@ -300,6 +358,7 @@ public final class FlatfileDatabaseManager implements DatabaseManager {
} }
public void newUser(String playerName) { public void newUser(String playerName) {
synchronized (fileWritingLock) {
try { try {
// Open the file to write the player // Open the file to write the player
BufferedWriter out = new BufferedWriter(new FileWriter(mcMMO.getUsersFilePath(), true)); BufferedWriter out = new BufferedWriter(new FileWriter(mcMMO.getUsersFilePath(), true));
@ -354,10 +413,12 @@ public final class FlatfileDatabaseManager implements DatabaseManager {
e.printStackTrace(); e.printStackTrace();
} }
} }
}
public PlayerProfile loadPlayerProfile(String playerName, boolean create) { public PlayerProfile loadPlayerProfile(String playerName, boolean create) {
FileReader file = null; FileReader file = null;
BufferedReader in = null; BufferedReader in = null;
synchronized (fileWritingLock) {
try { try {
// Open the user file // Open the user file
file = new FileReader(mcMMO.getUsersFilePath()); file = new FileReader(mcMMO.getUsersFilePath());
@ -390,6 +451,7 @@ public final class FlatfileDatabaseManager implements DatabaseManager {
e.printStackTrace(); e.printStackTrace();
} }
} }
}
if (create) { if (create) {
newUser(playerName); newUser(playerName);
@ -402,6 +464,7 @@ public final class FlatfileDatabaseManager implements DatabaseManager {
FileReader file = null; FileReader file = null;
BufferedReader in = null; BufferedReader in = null;
synchronized (fileWritingLock) {
try { try {
// Open the user file // Open the user file
file = new FileReader(mcMMO.getUsersFilePath()); file = new FileReader(mcMMO.getUsersFilePath());
@ -435,6 +498,7 @@ public final class FlatfileDatabaseManager implements DatabaseManager {
} }
} }
} }
}
public boolean checkConnected() { public boolean checkConnected() {
// Not implemented // Not implemented
@ -444,6 +508,8 @@ public final class FlatfileDatabaseManager implements DatabaseManager {
public List<String> getStoredUsers() { public List<String> getStoredUsers() {
ArrayList<String> users = new ArrayList<String>(); ArrayList<String> users = new ArrayList<String>();
BufferedReader in = null; BufferedReader in = null;
synchronized (fileWritingLock) {
try { try {
// Open the user file // Open the user file
FileReader file = new FileReader(mcMMO.getUsersFilePath()); FileReader file = new FileReader(mcMMO.getUsersFilePath());
@ -465,6 +531,7 @@ public final class FlatfileDatabaseManager implements DatabaseManager {
e.printStackTrace(); e.printStackTrace();
} }
} }
}
return users; return users;
} }