forked from taylorkelly/BigBrother
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
N3X15
committed
May 1, 2011
1 parent
fd9371a
commit c6f6b9d
Showing
1 changed file
with
180 additions
and
177 deletions.
There are no files selected for viewing
357 changes: 180 additions & 177 deletions
357
src/main/java/me/taylorkelly/bigbrother/tablemgrs/BBDataMySQL.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,177 +1,180 @@ | ||
package me.taylorkelly.bigbrother.tablemgrs; | ||
|
||
import java.sql.Connection; | ||
import java.sql.ResultSet; | ||
import java.sql.SQLException; | ||
import java.sql.Statement; | ||
import me.taylorkelly.bigbrother.BBLogging; | ||
import me.taylorkelly.bigbrother.BBSettings; | ||
import me.taylorkelly.bigbrother.datasource.ConnectionManager; | ||
|
||
/** | ||
* BBDataTable, but for MySQL | ||
* | ||
* @author N3X15 | ||
*/ | ||
public class BBDataMySQL extends BBDataTable { | ||
public final int revision = 1; | ||
public String toString() { | ||
return "BBData MySQL Driver r"+Integer.valueOf(revision); | ||
} | ||
|
||
|
||
|
||
/** | ||
* Returns "LOW_PRIORITY" for MySQL when mysqlLowPrioInserts is set. | ||
* | ||
* @return LOW_PRIORITY | "" | ||
*/ | ||
public static String getMySQLIgnore() { | ||
if (BBSettings.mysqlLowPrioInserts) { | ||
return " LOW_PRIORITY "; | ||
} else { | ||
return " "; | ||
} | ||
} | ||
|
||
@Override | ||
public String getPreparedDataBlockStatement() throws SQLException { | ||
return "INSERT "+getMySQLIgnore()+" INTO " + getTableName() | ||
+ " (date, player, action, world, x, y, z, type, data, rbacked) VALUES (?,?,?,?,?,?,?,?,?,0)"; | ||
} | ||
|
||
/* (non-Javadoc) | ||
* @see me.taylorkelly.bigbrother.tablemgrs.DBTable#getCreateSyntax() | ||
*/ | ||
@Override | ||
public String getCreateSyntax() { | ||
return "CREATE TABLE `"+getTableName()+"` (" | ||
+ "`id` INT NOT NULL AUTO_INCREMENT," | ||
+ "`date` INT UNSIGNED NOT NULL DEFAULT '0'," | ||
+ "`player` INT UNSIGNED NOT NULL DEFAULT 0," | ||
+ "`action` tinyint NOT NULL DEFAULT '0'," | ||
+ "`world` tinyint NOT NULL DEFAULT '0'," | ||
+ "`x` int NOT NULL DEFAULT '0'," | ||
+ "`y` tinyint UNSIGNED NOT NULL DEFAULT '0'," | ||
+ "`z` int NOT NULL DEFAULT '0'," | ||
+ "`type` smallint NOT NULL DEFAULT '0'," | ||
+ "`data` BLOB NOT NULL," | ||
+ "`rbacked` boolean NOT NULL DEFAULT '0'," | ||
+ "PRIMARY KEY (`id`)," | ||
+ "INDEX(`world`)," | ||
+ "INDEX(`x`,`y`,`z`)," | ||
+ "INDEX(`player`)," | ||
+ "INDEX(`action`)," | ||
+ "INDEX(`date`)," | ||
+ "INDEX(`type`)," | ||
+ "INDEX(`rbacked`)" | ||
+ ")"; | ||
} | ||
// GoMySQL suggested partitioning. Currently, I like the following modifier, | ||
// but it doesn't work on MySQL < 5.1. So we need to add a setting for | ||
// "enableMySQLPartitioning" or something | ||
// PARTITION BY LINEAR KEY(date) PARTITIONS 12; | ||
// Another stupid idea: use table comments for tracking table revision. | ||
|
||
|
||
/* (non-Javadoc) | ||
* @see me.taylorkelly.bigbrother.tablemgrs.DBTable#onLoad() | ||
*/ | ||
@Override | ||
public void onLoad() { | ||
// bbdata needs to be MyISAM, but the conversion takes forever. | ||
checkDBEngine(getTableName(), "MyISAM", true); | ||
} | ||
|
||
/** | ||
* Ensure we're using the right storage engine. | ||
* | ||
* @param tableName | ||
* @param requiredEngine | ||
*/ | ||
private void checkDBEngine(String tableName, String requiredEngine, boolean optional) { | ||
String engine = getEngine(tableName); | ||
if (engine == null) { | ||
return; // Error. | ||
} | ||
if (!engine.equalsIgnoreCase(requiredEngine)) { | ||
if (!optional) { | ||
BBLogging.warning("Changing " + tableName + " so that it uses " + requiredEngine + " instead of " + engine + ". THIS MAY TAKE A WHILE!"); | ||
setEngine(tableName, requiredEngine); | ||
} else { | ||
BBLogging.warning("Table " + tableName + " uses the MySQL storage engine " + engine + "."); | ||
BBLogging.info("For optimal performance, we suggest changing to " + requiredEngine + " via the following SQL statement:"); | ||
BBLogging.info(" ALTER TABLE " + tableName + " ENGINE = " + requiredEngine + ";"); | ||
BBLogging.info("Please note that, on many tables, this could take a very long time."); | ||
} | ||
} | ||
} | ||
|
||
private void setEngine(String tableName, String engine) { | ||
Connection conn = null; | ||
Statement st = null; | ||
try { | ||
conn = ConnectionManager.getConnection(); | ||
if(conn==null) return; | ||
st = conn.createStatement(); | ||
st.executeUpdate("ALTER TABLE " + tableName + " ENGINE = " + engine); | ||
conn.commit(); | ||
} catch (SQLException e) { | ||
BBLogging.severe("Altering " + tableName + " to use " + engine + " triggered an exception.", e); | ||
} finally { | ||
ConnectionManager.cleanup( "setEngine", conn, st, null ); | ||
} | ||
} | ||
|
||
private String getEngine(String tableName) { | ||
Connection conn = null; | ||
ResultSet rs = null; | ||
Statement stmt = null; | ||
String engine = null; | ||
try { | ||
conn = ConnectionManager.getConnection(); | ||
if(conn==null) return null; | ||
stmt = conn.createStatement(); | ||
if (!stmt.execute("SHOW TABLE STATUS WHERE Name = '" + tableName + "'")) { | ||
BBLogging.severe("Could not fetch table information for table " + tableName); | ||
return null; | ||
} | ||
rs = stmt.getResultSet(); | ||
rs.first(); | ||
engine = rs.getString("Engine"); | ||
} catch (SQLException e) { | ||
BBLogging.severe("Could not retreive table information.", e); | ||
} finally { | ||
ConnectionManager.cleanup( "getEngine", conn, stmt, rs ); | ||
} | ||
return engine; | ||
} | ||
|
||
|
||
|
||
@Override | ||
public String getCleanseAged(Long timeAgo, long deletesPerCleansing) { | ||
String cleansql = "DELETE FROM `"+getTableName()+"` WHERE date < " + timeAgo; | ||
if (BBSettings.deletesPerCleansing > 0) { | ||
cleansql += " LIMIT " + Long.valueOf(BBSettings.deletesPerCleansing); | ||
} | ||
cleansql += ";"; | ||
return cleansql; | ||
} | ||
|
||
|
||
|
||
@Override | ||
public String getCleanseByLimit(Long maxRecords, long deletesPerCleansing) { | ||
String cleansql = "DELETE FROM `"+getTableName()+"` LEFT OUTER JOIN (SELECT `id` FROM `bbdata` ORDER BY `id` DESC LIMIT 0," | ||
+ maxRecords | ||
+ ") AS `savedValues` ON `savedValues`.`id`=`bbdata`.`id` WHERE `savedValues`.`id` IS NULL"; | ||
if (deletesPerCleansing > 0) { | ||
cleansql += " LIMIT " + deletesPerCleansing; | ||
} | ||
cleansql += ";"; | ||
return cleansql; | ||
} | ||
|
||
|
||
} | ||
package me.taylorkelly.bigbrother.tablemgrs; | ||
|
||
import java.sql.Connection; | ||
import java.sql.ResultSet; | ||
import java.sql.SQLException; | ||
import java.sql.Statement; | ||
import me.taylorkelly.bigbrother.BBLogging; | ||
import me.taylorkelly.bigbrother.BBSettings; | ||
import me.taylorkelly.bigbrother.datasource.ConnectionManager; | ||
|
||
/** | ||
* BBDataTable, but for MySQL | ||
* | ||
* @author N3X15 | ||
*/ | ||
public class BBDataMySQL extends BBDataTable { | ||
public final int revision = 1; | ||
public String toString() { | ||
return "BBData MySQL Driver r"+Integer.valueOf(revision); | ||
} | ||
|
||
|
||
|
||
/** | ||
* Returns "LOW_PRIORITY" for MySQL when mysqlLowPrioInserts is set. | ||
* | ||
* @return LOW_PRIORITY | "" | ||
*/ | ||
public static String getMySQLIgnore() { | ||
if (BBSettings.mysqlLowPrioInserts) { | ||
return " LOW_PRIORITY "; | ||
} else { | ||
return " "; | ||
} | ||
} | ||
|
||
@Override | ||
public String getPreparedDataBlockStatement() throws SQLException { | ||
return "INSERT "+getMySQLIgnore()+" INTO " + getTableName() | ||
+ " (date, player, action, world, x, y, z, type, data, rbacked) VALUES (?,?,?,?,?,?,?,?,?,0)"; | ||
} | ||
|
||
/* (non-Javadoc) | ||
* @see me.taylorkelly.bigbrother.tablemgrs.DBTable#getCreateSyntax() | ||
*/ | ||
@Override | ||
public String getCreateSyntax() { | ||
return "CREATE TABLE `"+getTableName()+"` (" | ||
+ "`id` INT NOT NULL AUTO_INCREMENT," | ||
+ "`date` INT UNSIGNED NOT NULL DEFAULT '0'," | ||
+ "`player` INT UNSIGNED NOT NULL DEFAULT 0," | ||
+ "`action` tinyint NOT NULL DEFAULT '0'," | ||
+ "`world` tinyint NOT NULL DEFAULT '0'," | ||
+ "`x` int NOT NULL DEFAULT '0'," | ||
+ "`y` tinyint UNSIGNED NOT NULL DEFAULT '0'," | ||
+ "`z` int NOT NULL DEFAULT '0'," | ||
+ "`type` smallint NOT NULL DEFAULT '0'," | ||
+ "`data` BLOB NOT NULL," | ||
+ "`rbacked` boolean NOT NULL DEFAULT '0'," | ||
+ "PRIMARY KEY (`id`)," | ||
+ "INDEX(`world`)," | ||
+ "INDEX(`x`,`y`,`z`)," | ||
+ "INDEX(`player`)," | ||
+ "INDEX(`action`)," | ||
+ "INDEX(`date`)," | ||
+ "INDEX(`type`)," | ||
+ "INDEX(`rbacked`)" | ||
+ ")"; | ||
} | ||
// GoMySQL suggested partitioning. Currently, I like the following modifier, | ||
// but it doesn't work on MySQL < 5.1. So we need to add a setting for | ||
// "enableMySQLPartitioning" or something | ||
// PARTITION BY LINEAR KEY(date) PARTITIONS 12; | ||
// Another stupid idea: use table comments for tracking table revision. | ||
|
||
|
||
/* (non-Javadoc) | ||
* @see me.taylorkelly.bigbrother.tablemgrs.DBTable#onLoad() | ||
*/ | ||
@Override | ||
public void onLoad() { | ||
// bbdata needs to be MyISAM, but the conversion takes forever. | ||
checkDBEngine(getTableName(), "MyISAM", true); | ||
} | ||
|
||
/** | ||
* Ensure we're using the right storage engine. | ||
* | ||
* @param tableName | ||
* @param requiredEngine | ||
*/ | ||
private void checkDBEngine(String tableName, String requiredEngine, boolean optional) { | ||
String engine = getEngine(tableName); | ||
if (engine == null) { | ||
return; // Error. | ||
} | ||
if (!engine.equalsIgnoreCase(requiredEngine)) { | ||
if (!optional) { | ||
BBLogging.warning("Changing " + tableName + " so that it uses " + requiredEngine + " instead of " + engine + ". THIS MAY TAKE A WHILE!"); | ||
setEngine(tableName, requiredEngine); | ||
} else { | ||
BBLogging.warning("Table " + tableName + " uses the MySQL storage engine " + engine + "."); | ||
BBLogging.info("For optimal performance, we suggest changing to " + requiredEngine + " via the following SQL statement:"); | ||
BBLogging.info(" ALTER TABLE " + tableName + " ENGINE = " + requiredEngine + ";"); | ||
BBLogging.info("Please note that, on many tables, this could take a very long time."); | ||
} | ||
} | ||
} | ||
|
||
private void setEngine(String tableName, String engine) { | ||
Connection conn = null; | ||
Statement st = null; | ||
try { | ||
conn = ConnectionManager.getConnection(); | ||
if(conn==null) return; | ||
st = conn.createStatement(); | ||
st.executeUpdate("ALTER TABLE " + tableName + " ENGINE = " + engine); | ||
conn.commit(); | ||
} catch (SQLException e) { | ||
BBLogging.severe("Altering " + tableName + " to use " + engine + " triggered an exception.", e); | ||
} finally { | ||
ConnectionManager.cleanup( "setEngine", conn, st, null ); | ||
} | ||
} | ||
|
||
private String getEngine(String tableName) { | ||
Connection conn = null; | ||
ResultSet rs = null; | ||
Statement stmt = null; | ||
String engine = null; | ||
try { | ||
conn = ConnectionManager.getConnection(); | ||
if(conn==null) return null; | ||
stmt = conn.createStatement(); | ||
if (!stmt.execute("SHOW TABLE STATUS WHERE Name = '" + tableName + "'")) { | ||
BBLogging.severe("Could not fetch table information for table " + tableName); | ||
return null; | ||
} | ||
rs = stmt.getResultSet(); | ||
rs.first(); | ||
engine = rs.getString("Engine"); | ||
} catch (SQLException e) { | ||
BBLogging.severe("Could not retreive table information.", e); | ||
} finally { | ||
ConnectionManager.cleanup( "getEngine", conn, stmt, rs ); | ||
} | ||
return engine; | ||
} | ||
|
||
|
||
|
||
@Override | ||
public String getCleanseAged(Long timeAgo, long deletesPerCleansing) { | ||
String cleansql = "DELETE FROM `"+getTableName()+"` WHERE date < " + timeAgo; | ||
if (BBSettings.deletesPerCleansing > 0) { | ||
cleansql += " LIMIT " + Long.valueOf(BBSettings.deletesPerCleansing); | ||
} | ||
cleansql += ";"; | ||
return cleansql; | ||
} | ||
|
||
|
||
|
||
@Override | ||
public String getCleanseByLimit(Long maxRecords, long deletesPerCleansing) { | ||
// Fucking MySQL and your lack of subqueries LIMIT support. | ||
String cleansql = "CREATE TEMPORARY TABLE top_record SELECT id FROM bbdata ORDER BY id DESC LIMIT "+maxRecords; | ||
cleansql+="DELETE FROM bbdata WHERE id NOT IN (SELECT id FROM top_record) LIMIT "+deletesPerCleansing; | ||
cleansql+="DROP TABLE top_record;"; | ||
|
||
|
||
if (deletesPerCleansing > 0) { | ||
cleansql += " LIMIT " + deletesPerCleansing; | ||
} | ||
cleansql += ";"; | ||
return cleansql; | ||
} | ||
|
||
|
||
} |