Make the materials mappings safe to be used by multiple servers at the same time

This commit is contained in:
Brokkonaut
2018-08-01 16:53:34 +02:00
parent 7a5e46b65f
commit 5a7ba77095
3 changed files with 102 additions and 110 deletions

View File

@@ -398,14 +398,6 @@ public class Consumer extends TimerTask {
queue.add(new PlayerLeaveRow(player, onlineTime));
}
public void queueAddMaterialMapping(int key, String material) {
queue.add(new AddMaterialRow(key, material));
}
public void queueAddBlockStateMapping(int key, String blockState) {
queue.add(new AddBlockStateRow(key, blockState));
}
@Override
public synchronized void run() {
if (queue.isEmpty() || !lock.tryLock()) {
@@ -1046,56 +1038,6 @@ public class Consumer extends TimerTask {
}
}
private class AddMaterialRow implements Row {
private final int key;
private final String material;
AddMaterialRow(int key, String material) {
this.key = key;
this.material = material;
}
@Override
public String[] getInserts() {
return new String[] { "INSERT INTO `lb-materials` (id, name) VALUES (" + key + ",'" + mysqlTextEscape(material) + "');" };
}
@Override
public String[] getPlayers() {
return new String[0];
}
@Override
public Actor[] getActors() {
return new Actor[0];
}
}
private class AddBlockStateRow implements Row {
private final int key;
private final String blockstate;
AddBlockStateRow(int key, String blockstate) {
this.key = key;
this.blockstate = blockstate;
}
@Override
public String[] getInserts() {
return new String[] { "INSERT INTO `lb-blockstates` (id, name) VALUES (" + key + ",'" + mysqlTextEscape(blockstate) + "');" };
}
@Override
public String[] getPlayers() {
return new String[0];
}
@Override
public Actor[] getActors() {
return new Actor[0];
}
}
private int safeY(Location loc) {
int safeY = loc.getBlockY();
if (safeY < 0)

View File

@@ -1,11 +1,13 @@
package de.diddiz.LogBlock;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Arrays;
import java.util.HashMap;
import java.util.logging.Level;
import org.bukkit.Bukkit;
import org.bukkit.Material;
@@ -40,18 +42,32 @@ public class MaterialConverter {
materialString = blockDataString.substring(0, dataPart);
}
Integer key = materialToID.get(materialString);
if (key == null) {
key = nextMaterialId++;
materialToID.put(materialString, key);
int length = idToMaterial.length;
while (length <= key) {
length = (length * 3 / 2) + 5;
while (key == null) {
key = nextMaterialId;
Connection conn = LogBlock.getInstance().getConnection();
try {
conn.setAutoCommit(false);
PreparedStatement smt = conn.prepareStatement("INSERT IGNORE INTO `lb-materials` (id, name) VALUES (?, ?)");
smt.setInt(1, key);
smt.setString(2, materialString);
boolean couldAdd = smt.executeUpdate() > 0;
conn.commit();
smt.close();
if (couldAdd) {
internalAddMaterial(key, materialString);
} else {
initializeMaterials(conn);
}
} catch (SQLException e) {
LogBlock.getInstance().getLogger().log(Level.SEVERE, "Could not update lb-materials", e);
} finally {
try {
conn.close();
} catch (SQLException e) {
// ignored
}
}
if (length > idToMaterial.length) {
idToMaterial = Arrays.copyOf(idToMaterial, length);
}
idToMaterial[key] = materialString;
LogBlock.getInstance().getConsumer().queueAddMaterialMapping(key, materialString);
key = materialToID.get(materialString);
}
return key.intValue();
}
@@ -63,18 +79,32 @@ public class MaterialConverter {
}
String materialString = blockDataString.substring(dataPart);
Integer key = blockStateToID.get(materialString);
if (key == null) {
key = nextBlockStateId++;
blockStateToID.put(materialString, key);
int length = idToBlockState.length;
while (length <= key) {
length = (length * 3 / 2) + 5;
while (key == null) {
key = nextBlockStateId;
Connection conn = LogBlock.getInstance().getConnection();
try {
conn.setAutoCommit(false);
PreparedStatement smt = conn.prepareStatement("INSERT IGNORE INTO `lb-blockstates` (id, name) VALUES (?, ?)");
smt.setInt(1, key);
smt.setString(2, materialString);
boolean couldAdd = smt.executeUpdate() > 0;
conn.commit();
smt.close();
if (couldAdd) {
internalAddBlockState(key, materialString);
} else {
initializeMaterials(conn);
}
} catch (SQLException e) {
LogBlock.getInstance().getLogger().log(Level.SEVERE, "Could not update lb-blockstates", e);
} finally {
try {
conn.close();
} catch (SQLException e) {
// ignored
}
}
if (length > idToBlockState.length) {
idToBlockState = Arrays.copyOf(idToBlockState, length);
}
idToBlockState[key] = materialString;
LogBlock.getInstance().getConsumer().queueAddBlockStateMapping(key, materialString);
key = blockStateToID.get(materialString);
}
return key.intValue();
}
@@ -97,41 +127,47 @@ public class MaterialConverter {
while (rs.next()) {
int key = rs.getInt(1);
String materialString = rs.getString(2);
materialToID.put(materialString, key);
int length = idToMaterial.length;
while (length <= key) {
length = (length * 3 / 2) + 5;
}
if (length > idToMaterial.length) {
idToMaterial = Arrays.copyOf(idToMaterial, length);
}
idToMaterial[key] = materialString;
if (nextMaterialId <= key) {
nextMaterialId = key + 1;
}
internalAddMaterial(key, materialString);
}
rs.close();
rs = smt.executeQuery("SELECT id, name FROM `lb-blockstates`");
while (rs.next()) {
int key = rs.getInt(1);
String materialString = rs.getString(2);
blockStateToID.put(materialString, key);
int length = idToBlockState.length;
while (length <= key) {
length = (length * 3 / 2) + 5;
}
if (length > idToBlockState.length) {
idToBlockState = Arrays.copyOf(idToBlockState, length);
}
idToBlockState[key] = materialString;
if (nextBlockStateId <= key) {
nextBlockStateId = key + 1;
}
internalAddBlockState(key, materialString);
}
rs.close();
smt.close();
connection.close();
}
private synchronized static void internalAddMaterial(int key, String materialString) {
materialToID.put(materialString, key);
int length = idToMaterial.length;
while (length <= key) {
length = (length * 3 / 2) + 5;
}
if (length > idToMaterial.length) {
idToMaterial = Arrays.copyOf(idToMaterial, length);
}
idToMaterial[key] = materialString;
if (nextMaterialId <= key) {
nextMaterialId = key + 1;
}
}
private synchronized static void internalAddBlockState(int key, String materialString) {
blockStateToID.put(materialString, key);
int length = idToBlockState.length;
while (length <= key) {
length = (length * 3 / 2) + 5;
}
if (length > idToBlockState.length) {
idToBlockState = Arrays.copyOf(idToBlockState, length);
}
idToBlockState[key] = materialString;
if (nextBlockStateId <= key) {
nextBlockStateId = key + 1;
}
}
}

View File

@@ -47,9 +47,9 @@ class Updater {
logblock.saveConfig();
}
ComparableVersion configVersion = new ComparableVersion(versionString);
if (configVersion.compareTo(new ComparableVersion(logblock.getDescription().getVersion().replace(" (manually compiled)", ""))) >= 0) {
return false;
}
// if (configVersion.compareTo(new ComparableVersion(logblock.getDescription().getVersion().replace(" (manually compiled)", ""))) >= 0) {
// return false;
// }
if (configVersion.compareTo(new ComparableVersion("1.2.7")) < 0) {
logblock.getLogger().info("Updating tables to 1.2.7 ...");
if (isLogging(Logging.CHAT)) {
@@ -623,7 +623,7 @@ class Updater {
}
config.set("version", "1.13.0");
}
if (configVersion.compareTo(new ComparableVersion("1.13.1")) < 0) {
logblock.getLogger().info("Updating tables to 1.13.1 ...");
try {
@@ -717,6 +717,8 @@ class Updater {
if (isLogging(Logging.CHAT)) {
checkCharset("lb-chat", "message", st, true);
}
createIndexIfDoesNotExist("lb-materials", "name", "UNIQUE KEY `name` (`name`(250))", st, true);
createIndexIfDoesNotExist("lb-blockstates", "name", "UNIQUE KEY `name` (`name`(250))", st, true);
st.close();
conn.close();
@@ -729,6 +731,17 @@ class Updater {
return true;
}
void createIndexIfDoesNotExist(String table, String indexName, String definition, Statement st, boolean silent) throws SQLException {
final ResultSet rs = st.executeQuery("SHOW INDEX FROM `" + table + "` WHERE Key_name = '" + indexName + "'");
if (!rs.next()) {
st.execute("ALTER TABLE `" + table + "` ADD " + definition);
logblock.getLogger().info("Add index " + indexName + " to table " + table + ": Table modified");
} else if (!silent) {
logblock.getLogger().info("Add index " + indexName + " to table " + table + ": Already fine, skipping it");
}
rs.close();
}
void checkCharset(String table, String column, Statement st, boolean silent) throws SQLException {
final ResultSet rs = st.executeQuery("SHOW FULL COLUMNS FROM `" + table + "` WHERE field = '" + column + "'");
String charset = "utf8";
@@ -741,6 +754,7 @@ class Updater {
} else if (!silent) {
logblock.getLogger().info("Table " + table + " already fine, skipping it");
}
rs.close();
}
void checkTables() throws SQLException {