Keep track of beatmap cache size.

The minimum batch loading size is now based on the beatmap cache size instead of an arbitrary constant.

Signed-off-by: Jeffrey Han <itdelatrisu@gmail.com>
This commit is contained in:
Jeffrey Han 2015-03-08 13:36:26 -04:00
parent f9878f4fa4
commit 0b03912b7a

View File

@ -41,10 +41,10 @@ public class OsuDB {
* Current database version. * Current database version.
* This value should be changed whenever the database format changes. * This value should be changed whenever the database format changes.
*/ */
private static final String DATABASE_VERSION = "2014-03-04"; private static final String DATABASE_VERSION = "2014-03-08";
/** Minimum batch size to invoke batch loading. */ /** Minimum batch size ratio ({@code batchSize/cacheSize}) to invoke batch loading. */
private static final int LOAD_BATCH_MIN = 100; private static final float LOAD_BATCH_MIN_RATIO = 0.2f;
/** Minimum batch size to invoke batch insertion. */ /** Minimum batch size to invoke batch insertion. */
private static final int INSERT_BATCH_MIN = 100; private static final int INSERT_BATCH_MIN = 100;
@ -56,7 +56,10 @@ public class OsuDB {
private static Connection connection; private static Connection connection;
/** Query statements. */ /** Query statements. */
private static PreparedStatement insertStmt, selectStmt, deleteMapStmt, deleteGroupStmt; private static PreparedStatement insertStmt, selectStmt, deleteMapStmt, deleteGroupStmt, updateSizeStmt;
/** Current size of beatmap cache table. */
private static int cacheSize = -1;
// This class should not be instantiated. // This class should not be instantiated.
private OsuDB() {} private OsuDB() {}
@ -73,6 +76,9 @@ public class OsuDB {
// create the database // create the database
createDatabase(); createDatabase();
// retrieve the cache size
getCacheSize();
// check the database version // check the database version
checkVersion(); checkVersion();
@ -86,6 +92,7 @@ public class OsuDB {
selectStmt = connection.prepareStatement("SELECT * FROM beatmaps WHERE dir = ? AND file = ?"); selectStmt = connection.prepareStatement("SELECT * FROM beatmaps WHERE dir = ? AND file = ?");
deleteMapStmt = connection.prepareStatement("DELETE FROM beatmaps WHERE dir = ? AND file = ?"); deleteMapStmt = connection.prepareStatement("DELETE FROM beatmaps WHERE dir = ? AND file = ?");
deleteGroupStmt = connection.prepareStatement("DELETE FROM beatmaps WHERE dir = ?"); deleteGroupStmt = connection.prepareStatement("DELETE FROM beatmaps WHERE dir = ?");
updateSizeStmt = connection.prepareStatement("REPLACE INTO info (key, value) VALUES ('size', ?)");
} catch (SQLException e) { } catch (SQLException e) {
ErrorHandler.error("Failed to prepare beatmap statements.", e, true); ErrorHandler.error("Failed to prepare beatmap statements.", e, true);
} }
@ -128,9 +135,6 @@ public class OsuDB {
* from the current version, then updates the version field. * from the current version, then updates the version field.
*/ */
private static void checkVersion() { private static void checkVersion() {
if (connection == null)
return;
try (Statement stmt = connection.createStatement()) { try (Statement stmt = connection.createStatement()) {
// get the stored version // get the stored version
String sql = "SELECT value FROM info WHERE key = 'version'"; String sql = "SELECT value FROM info WHERE key = 'version'";
@ -152,6 +156,39 @@ public class OsuDB {
} }
} }
/**
* Retrieves the size of the beatmap cache from the 'info' table.
*/
private static void getCacheSize() {
try (Statement stmt = connection.createStatement()) {
String sql = "SELECT value FROM info WHERE key = 'size'";
ResultSet rs = stmt.executeQuery(sql);
try {
cacheSize = (rs.next()) ? Integer.parseInt(rs.getString(1)) : 0;
} catch (NumberFormatException e) {
cacheSize = 0;
}
rs.close();
} catch (SQLException e) {
ErrorHandler.error("Could not get beatmap cache size.", e, true);
}
}
/**
* Updates the size of the beatmap cache in the 'info' table.
*/
private static void updateCacheSize() {
if (connection == null)
return;
try {
updateSizeStmt.setString(1, Integer.toString(Math.max(cacheSize, 0)));
updateSizeStmt.executeUpdate();
} catch (SQLException e) {
ErrorHandler.error("Could not update beatmap cache size.", e, true);
}
}
/** /**
* Clears the database. * Clears the database.
*/ */
@ -163,6 +200,8 @@ public class OsuDB {
try (Statement stmt = connection.createStatement()) { try (Statement stmt = connection.createStatement()) {
String sql = "DROP TABLE beatmaps"; String sql = "DROP TABLE beatmaps";
stmt.executeUpdate(sql); stmt.executeUpdate(sql);
cacheSize = 0;
updateCacheSize();
} catch (SQLException e) { } catch (SQLException e) {
ErrorHandler.error("Could not drop beatmap database.", e, true); ErrorHandler.error("Could not drop beatmap database.", e, true);
} }
@ -179,7 +218,8 @@ public class OsuDB {
try { try {
setStatementFields(insertStmt, osu); setStatementFields(insertStmt, osu);
insertStmt.executeUpdate(); cacheSize += insertStmt.executeUpdate();
updateCacheSize();
} catch (SQLException e) { } catch (SQLException e) {
ErrorHandler.error("Failed to add beatmap to database.", e, true); ErrorHandler.error("Failed to add beatmap to database.", e, true);
} }
@ -210,7 +250,11 @@ public class OsuDB {
setStatementFields(insertStmt, osu); setStatementFields(insertStmt, osu);
insertStmt.addBatch(); insertStmt.addBatch();
} }
insertStmt.executeBatch(); int[] results = insertStmt.executeBatch();
for (int i = 0; i < results.length; i++) {
if (results[i] > 0)
cacheSize += results[i];
}
// re-create indexes // re-create indexes
if (recreateIndexes) { if (recreateIndexes) {
@ -221,6 +265,9 @@ public class OsuDB {
// restore previous auto-commit mode // restore previous auto-commit mode
connection.commit(); connection.commit();
connection.setAutoCommit(autoCommit); connection.setAutoCommit(autoCommit);
// update cache size
updateCacheSize();
} catch (SQLException e) { } catch (SQLException e) {
ErrorHandler.error("Failed to add beatmaps to database.", e, true); ErrorHandler.error("Failed to add beatmaps to database.", e, true);
} }
@ -313,7 +360,7 @@ public class OsuDB {
// batch size too small // batch size too small
int size = batch.size(); int size = batch.size();
if (size < LOAD_BATCH_MIN) { if (size < cacheSize * LOAD_BATCH_MIN_RATIO) {
for (OsuFile osu : batch) for (OsuFile osu : batch)
load(osu, flag); load(osu, flag);
return; return;
@ -452,7 +499,8 @@ public class OsuDB {
try { try {
deleteMapStmt.setString(1, dir); deleteMapStmt.setString(1, dir);
deleteMapStmt.setString(2, file); deleteMapStmt.setString(2, file);
deleteMapStmt.executeUpdate(); cacheSize -= deleteMapStmt.executeUpdate();
updateCacheSize();
} catch (SQLException e) { } catch (SQLException e) {
ErrorHandler.error("Failed to delete beatmap entry from database.", e, true); ErrorHandler.error("Failed to delete beatmap entry from database.", e, true);
} }
@ -468,7 +516,8 @@ public class OsuDB {
try { try {
deleteGroupStmt.setString(1, dir); deleteGroupStmt.setString(1, dir);
deleteGroupStmt.executeUpdate(); cacheSize -= deleteGroupStmt.executeUpdate();
updateCacheSize();
} catch (SQLException e) { } catch (SQLException e) {
ErrorHandler.error("Failed to delete beatmap group entry from database.", e, true); ErrorHandler.error("Failed to delete beatmap group entry from database.", e, true);
} }
@ -486,6 +535,7 @@ public class OsuDB {
selectStmt.close(); selectStmt.close();
deleteMapStmt.close(); deleteMapStmt.close();
deleteGroupStmt.close(); deleteGroupStmt.close();
updateSizeStmt.close();
connection.close(); connection.close();
connection = null; connection = null;
} catch (SQLException e) { } catch (SQLException e) {