Skip to content

Commit 0cfc857

Browse files
committed
Switched to H2 for cache database (closes #71)
1 parent 72fa14a commit 0cfc857

2 files changed

Lines changed: 39 additions & 22 deletions

File tree

core/pom.xml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -85,11 +85,11 @@
8585
<version>3.5.5</version>
8686
</dependency>
8787

88-
<!-- JDBC (cache) -->
88+
<!-- H2 (cache) -->
8989
<dependency>
90-
<groupId>org.xerial</groupId>
91-
<artifactId>sqlite-jdbc</artifactId>
92-
<version>3.27.2</version>
90+
<groupId>com.h2database</groupId>
91+
<artifactId>h2</artifactId>
92+
<version>1.4.199</version>
9393
</dependency>
9494

9595
<!-- HTTP -->

core/src/main/java/xyz/gianlu/librespot/cache/CacheManager.java

Lines changed: 35 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -48,10 +48,11 @@ public CacheManager(@NotNull Configuration conf) throws IOException {
4848
throw new IOException("Couldn't create cache directory!");
4949

5050
try {
51-
File tableFile = new File(parent, "table.sqlite");
52-
this.table = DriverManager.getConnection("jdbc:sqlite:" + tableFile.getAbsolutePath());
51+
File tableFile = new File(parent, "table");
52+
this.table = DriverManager.getConnection("jdbc:h2:" + tableFile.getAbsolutePath());
5353
createTablesIfNeeded();
5454

55+
deleteCorruptedEntries();
5556
if (conf.doCleanUp()) doCleanUp();
5657
} catch (SQLException ex) {
5758
throw new IOException(ex);
@@ -75,6 +76,31 @@ private static File getCacheFile(@NotNull File parent, @NotNull String hex) thro
7576
return new File(parent, hex);
7677
}
7778

79+
private static boolean exists(@NotNull File parent, @NotNull String hex) {
80+
String firstLevel = hex.substring(0, 2);
81+
String secondLevel = hex.substring(2, 4);
82+
83+
parent = new File(parent, "/" + firstLevel + "/" + secondLevel + "/");
84+
return new File(parent, hex).exists();
85+
}
86+
87+
private void deleteCorruptedEntries() throws SQLException, IOException {
88+
if (!enabled) return;
89+
90+
List<String> toRemove = new ArrayList<>();
91+
try (PreparedStatement statement = table.prepareStatement("SELECT DISTINCT fileId FROM Headers")) {
92+
ResultSet set = statement.executeQuery();
93+
while (set.next()) {
94+
String fileId = set.getString("fileId");
95+
if (!exists(parent, fileId))
96+
toRemove.add(fileId);
97+
}
98+
}
99+
100+
for (String fileId : toRemove)
101+
remove(fileId);
102+
}
103+
78104
private void doCleanUp() throws SQLException, IOException {
79105
if (!enabled) return;
80106

@@ -104,7 +130,7 @@ private void remove(@NotNull String fileIdHex) throws SQLException, IOException
104130
}
105131

106132
File file = getCacheFile(parent, fileIdHex);
107-
if (!file.delete())
133+
if (file.exists() && !file.delete())
108134
LOGGER.warn("Couldn't delete cache file: " + file.getAbsolutePath());
109135

110136
LOGGER.trace(String.format("Removed %s from cache.", fileIdHex));
@@ -114,11 +140,11 @@ private void createTablesIfNeeded() throws SQLException {
114140
if (!enabled) return;
115141

116142
try (Statement statement = table.createStatement()) {
117-
statement.execute("CREATE TABLE IF NOT EXISTS Chunks ( `fileId` TEXT NOT NULL, `chunkIndex` INTEGER NOT NULL, `available` INTEGER NOT NULL, PRIMARY KEY(`fileId`,`chunkIndex`) )");
143+
statement.execute("CREATE TABLE IF NOT EXISTS Chunks ( `fileId` VARCHAR NOT NULL, `chunkIndex` INTEGER NOT NULL, `available` INTEGER NOT NULL, PRIMARY KEY(`fileId`,`chunkIndex`) )");
118144
}
119145

120146
try (Statement statement = table.createStatement()) {
121-
statement.execute("CREATE TABLE IF NOT EXISTS Headers ( `fileId` TEXT NOT NULL, `id` TEXT NOT NULL, `value` TEXT NOT NULL, PRIMARY KEY(`fileId`,`id`) )");
147+
statement.execute("CREATE TABLE IF NOT EXISTS Headers ( `fileId` VARCHAR NOT NULL, `id` VARCHAR NOT NULL, `value` VARCHAR NOT NULL, PRIMARY KEY(`fileId`,`id`) )");
122148
}
123149
}
124150

@@ -134,16 +160,7 @@ public CacheManager.Handler forFileId(@NotNull ByteString fileId) throws IOExcep
134160

135161
Handler handler = handlers.get(fileId);
136162
if (handler == null) {
137-
File file = getCacheFile(parent, fileId);
138-
if (!file.exists()) {
139-
try {
140-
remove(Utils.bytesToHex(fileId));
141-
} catch (SQLException ex) {
142-
throw new IOException(ex);
143-
}
144-
}
145-
146-
handler = new Handler(fileId, file);
163+
handler = new Handler(fileId, getCacheFile(parent, fileId));
147164
handlers.put(fileId, handler);
148165
}
149166

@@ -199,7 +216,7 @@ private Handler(@NotNull ByteString fileId, @NotNull File file) throws IOExcepti
199216
private void updateTimestamp() {
200217
if (updatedTimestamp) return;
201218

202-
try (PreparedStatement statement = table.prepareStatement("INSERT OR REPLACE INTO Headers (fileId, id, value) VALUES (?, ?, ?)")) {
219+
try (PreparedStatement statement = table.prepareStatement("MERGE INTO Headers (fileId, id, value) VALUES (?, ?, ?)")) {
203220
statement.setString(1, Utils.bytesToHex(fileId));
204221
statement.setString(2, Utils.byteToHex(HEADER_TIMESTAMP));
205222
statement.setString(3, Utils.bytesToHex(BigInteger.valueOf(System.currentTimeMillis() / 1000).toByteArray()));
@@ -212,7 +229,7 @@ private void updateTimestamp() {
212229
}
213230

214231
public void setHeader(byte id, byte[] value) throws SQLException {
215-
try (PreparedStatement statement = table.prepareStatement("INSERT OR REPLACE INTO Headers (fileId, id, value) VALUES (?, ?, ?)")) {
232+
try (PreparedStatement statement = table.prepareStatement("MERGE INTO Headers (fileId, id, value) VALUES (?, ?, ?)")) {
216233
statement.setString(1, Utils.bytesToHex(fileId));
217234
statement.setString(2, Utils.byteToHex(id));
218235
statement.setString(3, Utils.bytesToHex(value));
@@ -293,7 +310,7 @@ public void writeChunk(byte[] buffer, int index) throws IOException, SQLExceptio
293310
io.write(buffer);
294311
}
295312

296-
try (PreparedStatement statement = table.prepareStatement("INSERT OR REPLACE INTO Chunks (fileId, chunkIndex, available) VALUES (?, ?, ?)")) {
313+
try (PreparedStatement statement = table.prepareStatement("MERGE INTO Chunks (fileId, chunkIndex, available) VALUES (?, ?, ?)")) {
297314
statement.setString(1, Utils.bytesToHex(fileId));
298315
statement.setInt(2, index);
299316
statement.setInt(3, 1);

0 commit comments

Comments
 (0)