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)); 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 @Override
public synchronized void run() { public synchronized void run() {
if (queue.isEmpty() || !lock.tryLock()) { 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) { private int safeY(Location loc) {
int safeY = loc.getBlockY(); int safeY = loc.getBlockY();
if (safeY < 0) if (safeY < 0)

View File

@@ -1,11 +1,13 @@
package de.diddiz.LogBlock; package de.diddiz.LogBlock;
import java.sql.Connection; import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet; import java.sql.ResultSet;
import java.sql.SQLException; import java.sql.SQLException;
import java.sql.Statement; import java.sql.Statement;
import java.util.Arrays; import java.util.Arrays;
import java.util.HashMap; import java.util.HashMap;
import java.util.logging.Level;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.Material; import org.bukkit.Material;
@@ -40,18 +42,32 @@ public class MaterialConverter {
materialString = blockDataString.substring(0, dataPart); materialString = blockDataString.substring(0, dataPart);
} }
Integer key = materialToID.get(materialString); Integer key = materialToID.get(materialString);
if (key == null) { while (key == null) {
key = nextMaterialId++; key = nextMaterialId;
materialToID.put(materialString, key); Connection conn = LogBlock.getInstance().getConnection();
int length = idToMaterial.length; try {
while (length <= key) { conn.setAutoCommit(false);
length = (length * 3 / 2) + 5; 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) { key = materialToID.get(materialString);
idToMaterial = Arrays.copyOf(idToMaterial, length);
}
idToMaterial[key] = materialString;
LogBlock.getInstance().getConsumer().queueAddMaterialMapping(key, materialString);
} }
return key.intValue(); return key.intValue();
} }
@@ -63,18 +79,32 @@ public class MaterialConverter {
} }
String materialString = blockDataString.substring(dataPart); String materialString = blockDataString.substring(dataPart);
Integer key = blockStateToID.get(materialString); Integer key = blockStateToID.get(materialString);
if (key == null) { while (key == null) {
key = nextBlockStateId++; key = nextBlockStateId;
blockStateToID.put(materialString, key); Connection conn = LogBlock.getInstance().getConnection();
int length = idToBlockState.length; try {
while (length <= key) { conn.setAutoCommit(false);
length = (length * 3 / 2) + 5; 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) { key = blockStateToID.get(materialString);
idToBlockState = Arrays.copyOf(idToBlockState, length);
}
idToBlockState[key] = materialString;
LogBlock.getInstance().getConsumer().queueAddBlockStateMapping(key, materialString);
} }
return key.intValue(); return key.intValue();
} }
@@ -97,41 +127,47 @@ public class MaterialConverter {
while (rs.next()) { while (rs.next()) {
int key = rs.getInt(1); int key = rs.getInt(1);
String materialString = rs.getString(2); String materialString = rs.getString(2);
internalAddMaterial(key, 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;
}
} }
rs.close(); rs.close();
rs = smt.executeQuery("SELECT id, name FROM `lb-blockstates`"); rs = smt.executeQuery("SELECT id, name FROM `lb-blockstates`");
while (rs.next()) { while (rs.next()) {
int key = rs.getInt(1); int key = rs.getInt(1);
String materialString = rs.getString(2); String materialString = rs.getString(2);
internalAddBlockState(key, 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;
}
} }
rs.close(); rs.close();
smt.close(); smt.close();
connection.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(); logblock.saveConfig();
} }
ComparableVersion configVersion = new ComparableVersion(versionString); ComparableVersion configVersion = new ComparableVersion(versionString);
if (configVersion.compareTo(new ComparableVersion(logblock.getDescription().getVersion().replace(" (manually compiled)", ""))) >= 0) { // if (configVersion.compareTo(new ComparableVersion(logblock.getDescription().getVersion().replace(" (manually compiled)", ""))) >= 0) {
return false; // return false;
} // }
if (configVersion.compareTo(new ComparableVersion("1.2.7")) < 0) { if (configVersion.compareTo(new ComparableVersion("1.2.7")) < 0) {
logblock.getLogger().info("Updating tables to 1.2.7 ..."); logblock.getLogger().info("Updating tables to 1.2.7 ...");
if (isLogging(Logging.CHAT)) { if (isLogging(Logging.CHAT)) {
@@ -623,7 +623,7 @@ class Updater {
} }
config.set("version", "1.13.0"); config.set("version", "1.13.0");
} }
if (configVersion.compareTo(new ComparableVersion("1.13.1")) < 0) { if (configVersion.compareTo(new ComparableVersion("1.13.1")) < 0) {
logblock.getLogger().info("Updating tables to 1.13.1 ..."); logblock.getLogger().info("Updating tables to 1.13.1 ...");
try { try {
@@ -717,6 +717,8 @@ class Updater {
if (isLogging(Logging.CHAT)) { if (isLogging(Logging.CHAT)) {
checkCharset("lb-chat", "message", st, true); 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(); st.close();
conn.close(); conn.close();
@@ -729,6 +731,17 @@ class Updater {
return true; 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 { 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 + "'"); final ResultSet rs = st.executeQuery("SHOW FULL COLUMNS FROM `" + table + "` WHERE field = '" + column + "'");
String charset = "utf8"; String charset = "utf8";
@@ -741,6 +754,7 @@ class Updater {
} else if (!silent) { } else if (!silent) {
logblock.getLogger().info("Table " + table + " already fine, skipping it"); logblock.getLogger().info("Table " + table + " already fine, skipping it");
} }
rs.close();
} }
void checkTables() throws SQLException { void checkTables() throws SQLException {