Fix potential database deadlocks

This commit is contained in:
Esophose 2020-03-13 13:09:52 -06:00
parent 80a4613725
commit 08405801b6

View file

@ -17,7 +17,6 @@ import dev.esophose.playerparticles.styles.ParticleStyle;
import dev.esophose.playerparticles.util.ParticleUtils; import dev.esophose.playerparticles.util.ParticleUtils;
import java.sql.PreparedStatement; import java.sql.PreparedStatement;
import java.sql.ResultSet; import java.sql.ResultSet;
import java.util.Collection;
import java.util.HashSet; import java.util.HashSet;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
@ -81,14 +80,11 @@ public class DataManager extends Manager {
* @return The PPlayer from cache * @return The PPlayer from cache
*/ */
public PPlayer getPPlayer(UUID playerUUID) { public PPlayer getPPlayer(UUID playerUUID) {
Collection<PPlayer> pplayers; for (PPlayer pp : this.playerParticles.getManager(ParticleManager.class).getPPlayers())
synchronized (pplayers = this.playerParticles.getManager(ParticleManager.class).getPPlayers()) { // Under rare circumstances, the PPlayers list can be changed while it's looping
for (PPlayer pp : pplayers)
if (pp.getUniqueId().equals(playerUUID)) if (pp.getUniqueId().equals(playerUUID))
return pp; return pp;
return null; return null;
} }
}
/** /**
* Gets a player from the save data, creates one if it doesn't exist and caches it * Gets a player from the save data, creates one if it doesn't exist and caches it
@ -253,12 +249,8 @@ public class DataManager extends Manager {
} }
this.sync(() -> { this.sync(() -> {
synchronized (loadedPPlayer) { this.playerParticles.getManager(ParticleManager.class).addPPlayer(loadedPPlayer);
if (this.getPPlayer(playerUUID) == null) { // Make sure the PPlayer still isn't added, since this is async it's possible it got ran twice
this.playerParticles.getManager(ParticleManager.class).addPPlayer(loadedPPlayer); // This will be fine now since loadedPPlayer is synchronized
callback.accept(loadedPPlayer); callback.accept(loadedPPlayer);
}
}
}); });
}); });
}); });
@ -312,6 +304,7 @@ public class DataManager extends Manager {
this.async(() -> this.databaseConnector.connect((connection) -> { this.async(() -> this.databaseConnector.connect((connection) -> {
String groupUUID; String groupUUID;
boolean existingGroup;
String groupUUIDQuery = "SELECT uuid FROM " + this.getTablePrefix() + "group WHERE owner_uuid = ? AND name = ?"; String groupUUIDQuery = "SELECT uuid FROM " + this.getTablePrefix() + "group WHERE owner_uuid = ? AND name = ?";
try (PreparedStatement statement = connection.prepareStatement(groupUUIDQuery)) { try (PreparedStatement statement = connection.prepareStatement(groupUUIDQuery)) {
@ -321,21 +314,25 @@ public class DataManager extends Manager {
ResultSet result = statement.executeQuery(); ResultSet result = statement.executeQuery();
if (result.next()) { // Clear out particles from existing group if (result.next()) { // Clear out particles from existing group
groupUUID = result.getString("uuid"); groupUUID = result.getString("uuid");
existingGroup = true;
String particlesDeleteQuery = "DELETE FROM " + this.getTablePrefix() + "particle WHERE group_uuid = ?";
PreparedStatement particlesDeleteStatement = connection.prepareStatement(particlesDeleteQuery);
particlesDeleteStatement.setString(1, result.getString("uuid"));
particlesDeleteStatement.executeUpdate();
} else { // Create new group } else { // Create new group
groupUUID = UUID.randomUUID().toString(); groupUUID = UUID.randomUUID().toString();
existingGroup = false;
}
}
if (existingGroup) {
String particlesDeleteQuery = "DELETE FROM " + this.getTablePrefix() + "particle WHERE group_uuid = ?";
try (PreparedStatement particlesDeleteStatement = connection.prepareStatement(particlesDeleteQuery)) {
particlesDeleteStatement.setString(1, groupUUID);
particlesDeleteStatement.executeUpdate();
}
} else {
String groupCreateQuery = "INSERT INTO " + this.getTablePrefix() + "group (uuid, owner_uuid, name) VALUES (?, ?, ?)"; String groupCreateQuery = "INSERT INTO " + this.getTablePrefix() + "group (uuid, owner_uuid, name) VALUES (?, ?, ?)";
PreparedStatement groupCreateStatement = connection.prepareStatement(groupCreateQuery); try (PreparedStatement groupCreateStatement = connection.prepareStatement(groupCreateQuery)) {
groupCreateStatement.setString(1, groupUUID); groupCreateStatement.setString(1, groupUUID);
groupCreateStatement.setString(2, playerUUID.toString()); groupCreateStatement.setString(2, playerUUID.toString());
groupCreateStatement.setString(3, group.getName()); groupCreateStatement.setString(3, group.getName());
groupCreateStatement.executeUpdate(); groupCreateStatement.executeUpdate();
} }
} }
@ -527,11 +524,7 @@ public class DataManager extends Manager {
* @param asyncCallback The callback to run on a separate thread * @param asyncCallback The callback to run on a separate thread
*/ */
private void async(Runnable asyncCallback) { private void async(Runnable asyncCallback) {
if (Bukkit.isPrimaryThread()) {
Bukkit.getScheduler().runTaskAsynchronously(this.playerParticles, asyncCallback); Bukkit.getScheduler().runTaskAsynchronously(this.playerParticles, asyncCallback);
} else {
asyncCallback.run();
}
} }
/** /**