mirror of
https://github.com/overleaf/overleaf.git
synced 2024-11-07 20:31:06 -05:00
Implement and test DBStore swap_table functionality
This commit is contained in:
parent
d2b628d904
commit
9d19cdd261
14 changed files with 252 additions and 47 deletions
|
@ -8,7 +8,11 @@ import java.sql.SQLException;
|
|||
*/
|
||||
public interface SQLUpdate {
|
||||
|
||||
public String getSQL();
|
||||
public void addParametersToStatement(PreparedStatement statement) throws SQLException;
|
||||
String getSQL();
|
||||
default void addParametersToStatement(
|
||||
PreparedStatement statement
|
||||
) throws SQLException {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -3,14 +3,14 @@ package uk.ac.ic.wlgitbridge.bridge.db.sqlite;
|
|||
import uk.ac.ic.wlgitbridge.bridge.db.DBInitException;
|
||||
import uk.ac.ic.wlgitbridge.bridge.db.DBStore;
|
||||
import uk.ac.ic.wlgitbridge.bridge.db.sqlite.query.GetLatestVersionForProjectSQLQuery;
|
||||
import uk.ac.ic.wlgitbridge.bridge.db.sqlite.query.GetOldestProjectName;
|
||||
import uk.ac.ic.wlgitbridge.bridge.db.sqlite.query.GetPathForURLInProjectSQLQuery;
|
||||
import uk.ac.ic.wlgitbridge.bridge.db.sqlite.query.GetProjectNamesSQLQuery;
|
||||
import uk.ac.ic.wlgitbridge.bridge.db.sqlite.update.create.CreateIndexURLIndexStore;
|
||||
import uk.ac.ic.wlgitbridge.bridge.db.sqlite.update.create.CreateProjectsTableSQLUpdate;
|
||||
import uk.ac.ic.wlgitbridge.bridge.db.sqlite.update.create.CreateURLIndexStoreSQLUpdate;
|
||||
import uk.ac.ic.wlgitbridge.bridge.db.sqlite.update.create.*;
|
||||
import uk.ac.ic.wlgitbridge.bridge.db.sqlite.update.delete.DeleteFilesForProjectSQLUpdate;
|
||||
import uk.ac.ic.wlgitbridge.bridge.db.sqlite.update.insert.AddURLIndexSQLUpdate;
|
||||
import uk.ac.ic.wlgitbridge.bridge.db.sqlite.update.insert.SetProjectSQLUpdate;
|
||||
import uk.ac.ic.wlgitbridge.bridge.db.sqlite.update.insert.SetProjectLastAccessedTime;
|
||||
|
||||
import java.io.File;
|
||||
import java.sql.*;
|
||||
|
@ -80,15 +80,15 @@ public class SqliteDBStore implements DBStore {
|
|||
|
||||
@Override
|
||||
public String getOldestUnswappedProject() {
|
||||
throw new UnsupportedOperationException();
|
||||
return query(new GetOldestProjectName());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setLastAccessedTime(
|
||||
String projectName,
|
||||
Timestamp time
|
||||
Timestamp lastAccessed
|
||||
) {
|
||||
throw new UnsupportedOperationException();
|
||||
update(new SetProjectLastAccessedTime(projectName, lastAccessed));
|
||||
}
|
||||
|
||||
private Connection openConnectionTo(File dbFile) {
|
||||
|
@ -117,7 +117,9 @@ public class SqliteDBStore implements DBStore {
|
|||
Stream.of(
|
||||
new CreateProjectsTableSQLUpdate(),
|
||||
new CreateURLIndexStoreSQLUpdate(),
|
||||
new CreateIndexURLIndexStore()
|
||||
new CreateIndexURLIndexStore(),
|
||||
new CreateSwapTable(),
|
||||
new CreateSwapTableIndex()
|
||||
).forEach(this::update);
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,30 @@
|
|||
package uk.ac.ic.wlgitbridge.bridge.db.sqlite.query;
|
||||
|
||||
import uk.ac.ic.wlgitbridge.bridge.db.sqlite.SQLQuery;
|
||||
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
|
||||
/**
|
||||
* Created by winston on 23/08/2016.
|
||||
*/
|
||||
public class GetOldestProjectName implements SQLQuery<String> {
|
||||
|
||||
private static final String GET_OLDEST_PROJECT_NAME =
|
||||
"SELECT `project_name`, MIN(`last_accessed`)\n" +
|
||||
" FROM `swap_table`";
|
||||
|
||||
@Override
|
||||
public String getSQL() {
|
||||
return GET_OLDEST_PROJECT_NAME;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String processResultSet(ResultSet resultSet) throws SQLException {
|
||||
while (resultSet.next()) {
|
||||
return resultSet.getString("project_name");
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
|
@ -2,7 +2,6 @@ package uk.ac.ic.wlgitbridge.bridge.db.sqlite.query;
|
|||
|
||||
import uk.ac.ic.wlgitbridge.bridge.db.sqlite.SQLQuery;
|
||||
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.util.LinkedList;
|
||||
|
@ -30,9 +29,4 @@ public class GetProjectNamesSQLQuery implements SQLQuery<List<String>> {
|
|||
return GET_URL_INDEXES_FOR_PROJECT_NAME;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addParametersToStatement(PreparedStatement statement) throws SQLException {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -2,25 +2,18 @@ package uk.ac.ic.wlgitbridge.bridge.db.sqlite.update.create;
|
|||
|
||||
import uk.ac.ic.wlgitbridge.bridge.db.sqlite.SQLUpdate;
|
||||
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.SQLException;
|
||||
|
||||
/**
|
||||
* Created by Winston on 21/02/15.
|
||||
*/
|
||||
public class CreateIndexURLIndexStore implements SQLUpdate {
|
||||
|
||||
public static final String CREATE_INDEX_URL_INDEX_STORE =
|
||||
"CREATE UNIQUE INDEX IF NOT EXISTS `project_path_index` ON `url_index_store`(`project_name`, `path`);\n";
|
||||
"CREATE UNIQUE INDEX IF NOT EXISTS `project_path_index` " +
|
||||
"ON `url_index_store`(`project_name`, `path`);\n";
|
||||
|
||||
@Override
|
||||
public String getSQL() {
|
||||
return CREATE_INDEX_URL_INDEX_STORE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addParametersToStatement(PreparedStatement statement) throws SQLException {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -2,9 +2,6 @@ package uk.ac.ic.wlgitbridge.bridge.db.sqlite.update.create;
|
|||
|
||||
import uk.ac.ic.wlgitbridge.bridge.db.sqlite.SQLUpdate;
|
||||
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.SQLException;
|
||||
|
||||
/**
|
||||
* Created by Winston on 20/11/14.
|
||||
*/
|
||||
|
@ -21,9 +18,4 @@ public class CreateProjectsTableSQLUpdate implements SQLUpdate {
|
|||
return CREATE_PROJECTS_TABLE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addParametersToStatement(PreparedStatement statement) throws SQLException {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,27 @@
|
|||
package uk.ac.ic.wlgitbridge.bridge.db.sqlite.update.create;
|
||||
|
||||
import uk.ac.ic.wlgitbridge.bridge.db.sqlite.SQLUpdate;
|
||||
|
||||
/**
|
||||
* Created by winston on 23/08/2016.
|
||||
*/
|
||||
public class CreateSwapTable implements SQLUpdate {
|
||||
|
||||
private static final String CREATE_SWAP_TABLE =
|
||||
"CREATE TABLE IF NOT EXISTS `swap_table` (\n" +
|
||||
" `project_name` VARCHAR NOT NULL DEFAULT '',\n" +
|
||||
" `last_accessed` DATETIME NULL DEFAULT 0,\n" +
|
||||
" PRIMARY KEY (`project_name`),\n" +
|
||||
" CONSTRAINT `swap_table_fk_1`\n" +
|
||||
" FOREIGN KEY (`project_name`)\n" +
|
||||
" REFERENCES `projects`(`name`)\n" +
|
||||
" ON DELETE CASCADE\n" +
|
||||
" ON UPDATE CASCADE\n" +
|
||||
")";
|
||||
|
||||
@Override
|
||||
public String getSQL() {
|
||||
return CREATE_SWAP_TABLE;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
package uk.ac.ic.wlgitbridge.bridge.db.sqlite.update.create;
|
||||
|
||||
import uk.ac.ic.wlgitbridge.bridge.db.sqlite.SQLUpdate;
|
||||
|
||||
/**
|
||||
* Created by winston on 23/08/2016.
|
||||
*/
|
||||
public class CreateSwapTableIndex implements SQLUpdate {
|
||||
|
||||
private static final String CREATE_SWAP_TABLE_INDEX =
|
||||
"CREATE INDEX IF NOT EXISTS `swap_table_index`\n" +
|
||||
" ON `swap_table`(`last_accessed`)";
|
||||
|
||||
@Override
|
||||
public String getSQL() {
|
||||
return CREATE_SWAP_TABLE_INDEX;
|
||||
}
|
||||
|
||||
}
|
|
@ -2,9 +2,6 @@ package uk.ac.ic.wlgitbridge.bridge.db.sqlite.update.create;
|
|||
|
||||
import uk.ac.ic.wlgitbridge.bridge.db.sqlite.SQLUpdate;
|
||||
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.SQLException;
|
||||
|
||||
/**
|
||||
* Created by Winston on 20/11/14.
|
||||
*/
|
||||
|
@ -16,7 +13,11 @@ public class CreateURLIndexStoreSQLUpdate implements SQLUpdate {
|
|||
" `url` text NOT NULL,\n"+
|
||||
" `path` text NOT NULL,\n"+
|
||||
" PRIMARY KEY (`project_name`,`url`),\n"+
|
||||
" CONSTRAINT `url_index_store_ibfk_1` FOREIGN KEY (`project_name`) REFERENCES `projects` (`name`) ON DELETE CASCADE ON UPDATE CASCADE\n"+
|
||||
" CONSTRAINT `url_index_store_ibfk_1` " +
|
||||
"FOREIGN KEY (`project_name`) " +
|
||||
"REFERENCES `projects` (`name`) " +
|
||||
"ON DELETE CASCADE " +
|
||||
"ON UPDATE CASCADE\n"+
|
||||
");\n";
|
||||
|
||||
@Override
|
||||
|
@ -24,9 +25,4 @@ public class CreateURLIndexStoreSQLUpdate implements SQLUpdate {
|
|||
return CREATE_URL_INDEX_STORE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addParametersToStatement(PreparedStatement statement) throws SQLException {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -11,7 +11,8 @@ import java.sql.SQLException;
|
|||
public class DeleteFilesForProjectSQLUpdate implements SQLUpdate {
|
||||
|
||||
private static final String DELETE_URL_INDEXES_FOR_PROJECT_NAME =
|
||||
"DELETE FROM `url_index_store` WHERE `project_name` = ? AND path IN (";
|
||||
"DELETE FROM `url_index_store` " +
|
||||
"WHERE `project_name` = ? AND path IN (";
|
||||
|
||||
private final String projectName;
|
||||
private final String[] paths;
|
||||
|
@ -23,7 +24,9 @@ public class DeleteFilesForProjectSQLUpdate implements SQLUpdate {
|
|||
|
||||
@Override
|
||||
public String getSQL() {
|
||||
StringBuilder sb = new StringBuilder(DELETE_URL_INDEXES_FOR_PROJECT_NAME);
|
||||
StringBuilder sb = new StringBuilder(
|
||||
DELETE_URL_INDEXES_FOR_PROJECT_NAME
|
||||
);
|
||||
for (int i = 0; i < paths.length; i++) {
|
||||
sb.append("?");
|
||||
if (i < paths.length - 1) {
|
||||
|
@ -35,7 +38,9 @@ public class DeleteFilesForProjectSQLUpdate implements SQLUpdate {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void addParametersToStatement(PreparedStatement statement) throws SQLException {
|
||||
public void addParametersToStatement(
|
||||
PreparedStatement statement
|
||||
) throws SQLException {
|
||||
statement.setString(1, projectName);
|
||||
for (int i = 0; i < paths.length; i++) {
|
||||
statement.setString(i + 2, paths[i]);
|
||||
|
|
|
@ -11,7 +11,12 @@ import java.sql.SQLException;
|
|||
public class AddURLIndexSQLUpdate implements SQLUpdate {
|
||||
|
||||
private static final String ADD_URL_INDEX =
|
||||
"INSERT OR REPLACE INTO `url_index_store` (`project_name`, `url`, `path`) VALUES (?, ?, ?);\n";
|
||||
"INSERT OR REPLACE INTO `url_index_store`(" +
|
||||
"`project_name`, " +
|
||||
"`url`, " +
|
||||
"`path`" +
|
||||
") VALUES " +
|
||||
"(?, ?, ?)\n";
|
||||
|
||||
private final String projectName;
|
||||
private final String url;
|
||||
|
@ -29,7 +34,9 @@ public class AddURLIndexSQLUpdate implements SQLUpdate {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void addParametersToStatement(PreparedStatement statement) throws SQLException {
|
||||
public void addParametersToStatement(
|
||||
PreparedStatement statement
|
||||
) throws SQLException {
|
||||
statement.setString(1, projectName);
|
||||
statement.setString(2, url);
|
||||
statement.setString(3, path);
|
||||
|
|
|
@ -0,0 +1,47 @@
|
|||
package uk.ac.ic.wlgitbridge.bridge.db.sqlite.update.insert;
|
||||
|
||||
import uk.ac.ic.wlgitbridge.bridge.db.sqlite.SQLUpdate;
|
||||
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.Timestamp;
|
||||
|
||||
/**
|
||||
* Created by winston on 23/08/2016.
|
||||
*/
|
||||
public class SetProjectLastAccessedTime implements SQLUpdate {
|
||||
|
||||
private static final String SET_PROJECT_LAST_ACCESSED_TIME =
|
||||
"INSERT OR REPLACE INTO `swap_table`(\n" +
|
||||
" `project_name`,\n" +
|
||||
" `last_accessed`\n" +
|
||||
") VALUES (\n" +
|
||||
" ?,\n" +
|
||||
" ?\n" +
|
||||
")";
|
||||
|
||||
private final String projectName;
|
||||
private final Timestamp lastAccessed;
|
||||
|
||||
public SetProjectLastAccessedTime(
|
||||
String projectName,
|
||||
Timestamp lastAccessed
|
||||
) {
|
||||
this.projectName = projectName;
|
||||
this.lastAccessed = lastAccessed;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSQL() {
|
||||
return SET_PROJECT_LAST_ACCESSED_TIME;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addParametersToStatement(
|
||||
PreparedStatement statement
|
||||
) throws SQLException {
|
||||
statement.setString(1, projectName);
|
||||
statement.setTimestamp(2, lastAccessed);
|
||||
}
|
||||
|
||||
}
|
|
@ -11,7 +11,8 @@ import java.sql.SQLException;
|
|||
public class SetProjectSQLUpdate implements SQLUpdate {
|
||||
|
||||
private static final String SET_PROJECT =
|
||||
"INSERT OR REPLACE INTO `projects`(`name`, `version_id`) VALUES (?, ?);\n";
|
||||
"INSERT OR REPLACE INTO `projects`(`name`, `version_id`) " +
|
||||
"VALUES (?, ?);\n";
|
||||
|
||||
private final String projectName;
|
||||
private final int versionID;
|
||||
|
|
|
@ -0,0 +1,88 @@
|
|||
package uk.ac.ic.wlgitbridge.bridge.db.sqlite;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.rules.TemporaryFolder;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.sql.Timestamp;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.temporal.ChronoUnit;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNull;
|
||||
|
||||
/**
|
||||
* Created by winston on 23/08/2016.
|
||||
*/
|
||||
public class SqliteDBStoreTest {
|
||||
|
||||
private SqliteDBStore dbStore;
|
||||
|
||||
@Before
|
||||
public void setup() throws IOException {
|
||||
TemporaryFolder tmpFolder = new TemporaryFolder();
|
||||
tmpFolder.create();
|
||||
dbStore = new SqliteDBStore(tmpFolder.newFile("dbStore.db"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void swapTableStartsOutEmpty() {
|
||||
assertNull(dbStore.getOldestUnswappedProject());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetOldestUnswappedProject() {
|
||||
dbStore.setLatestVersionForProject("older", 3);
|
||||
dbStore.setLastAccessedTime(
|
||||
"older",
|
||||
Timestamp.valueOf(
|
||||
LocalDateTime.now().minus(5, ChronoUnit.SECONDS)
|
||||
)
|
||||
);
|
||||
dbStore.setLatestVersionForProject("asdf", 1);
|
||||
dbStore.setLastAccessedTime(
|
||||
"asdf",
|
||||
Timestamp.valueOf(
|
||||
LocalDateTime.now().minus(1, ChronoUnit.SECONDS)
|
||||
)
|
||||
);
|
||||
assertEquals("older", dbStore.getOldestUnswappedProject());
|
||||
dbStore.setLastAccessedTime(
|
||||
"older",
|
||||
Timestamp.valueOf(
|
||||
LocalDateTime.now()
|
||||
)
|
||||
);
|
||||
assertEquals("asdf", dbStore.getOldestUnswappedProject());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void noOldestProjectIfAllEvicated() {
|
||||
dbStore.setLatestVersionForProject("older", 3);
|
||||
dbStore.setLastAccessedTime("older", null);
|
||||
assertNull(dbStore.getOldestUnswappedProject());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void nullLastAccessedTimesDoNotCount() {
|
||||
dbStore.setLatestVersionForProject("older", 2);
|
||||
dbStore.setLastAccessedTime(
|
||||
"older",
|
||||
Timestamp.valueOf(
|
||||
LocalDateTime.now().minus(5, ChronoUnit.SECONDS)
|
||||
)
|
||||
);
|
||||
dbStore.setLatestVersionForProject("newer", 3);
|
||||
dbStore.setLastAccessedTime(
|
||||
"newer",
|
||||
Timestamp.valueOf(
|
||||
LocalDateTime.now()
|
||||
)
|
||||
);
|
||||
assertEquals("older", dbStore.getOldestUnswappedProject());
|
||||
dbStore.setLastAccessedTime("older", null);
|
||||
assertEquals("newer", dbStore.getOldestUnswappedProject());
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in a new issue