diff --git a/services/git-bridge/Makefile b/services/git-bridge/Makefile
index 3a24af8ad8..2fd30f0fa5 100644
--- a/services/git-bridge/Makefile
+++ b/services/git-bridge/Makefile
@@ -16,6 +16,15 @@ $(MVN_TARGET): $(shell find src -type f) pom.xml
build: $(MVN_TARGET)
+
+format:
+ mvn $(MVN_OPTS) com.spotify.fmt:fmt-maven-plugin:check
+
+
+format_fix:
+ mvn $(MVN_OPTS) com.spotify.fmt:fmt-maven-plugin:format
+
+
test:
mvn $(MVN_OPTS) test
diff --git a/services/git-bridge/pom.xml b/services/git-bridge/pom.xml
index 6f4b3f2f72..16fba4a94e 100644
--- a/services/git-bridge/pom.xml
+++ b/services/git-bridge/pom.xml
@@ -8,19 +8,43 @@
writelatex-git-bridge
1.0-SNAPSHOT
+ 1.8
UTF-8
-
+ 3.7.0
+ 2.12.4
+ 3.1.0
+ 2.23
+ 4.13.2
+ 2.8.4
+ 9.4.51.v20230217
+ 2.9.0
+ 2.12.3
+ 6.6.1.202309021850-r
+ 3.41.2.2
+ 2.9.9
+ 1.34.1
+ 1.23.0
+ 3.12.0
+ 1.2.3
+ 5.12.0
+ 3.11.1
+ 1.11.274
+ ${jaxb.runtime.version}
+ 2.3.2
+ 4.5.14
+ 2.10.0
+ 1.24.0
+ 0.10.0
maven-compiler-plugin
- 3.7.0
+ ${maven.compiler.plugin.version}
- 1.8
- 1.8
-
+ ${java.version}
+ ${java.version}
@@ -28,7 +52,7 @@
org.apache.maven.plugins
maven-surefire-plugin
- 2.12.4
+ ${maven.surefire.plugin.version}
-Djdk.net.URLClassPath.disableClassPathURLCheck=true
@@ -36,7 +60,7 @@
maven-assembly-plugin
- 3.1.0
+ ${maven.assembly.plugin.version}
package
@@ -56,6 +80,11 @@
+
+ com.spotify.fmt
+ fmt-maven-plugin
+ ${fmt.plugin.version}
+
@@ -63,169 +92,169 @@
junit
junit
- 4.13.2
+ ${junit.version}
test
org.jmock
jmock-junit4
- 2.8.4
+ ${jmock.junit4.version}
test
org.eclipse.jetty
jetty-servlet
- 9.4.51.v20230217
+ ${jetty.servlet.version}
org.eclipse.jetty
jetty-server
- 9.4.51.v20230217
+ ${jetty.servlet.version}
com.google.code.gson
gson
- 2.9.0
+ ${gson.version}
org.asynchttpclient
async-http-client
- 2.12.3
+ ${async.http.client.version}
org.eclipse.jgit
org.eclipse.jgit
- 6.6.1.202309021850-r
+ ${jgit.version}
org.eclipse.jgit
org.eclipse.jgit.http.server
- 6.6.1.202309021850-r
+ ${jgit.version}
org.xerial
sqlite-jdbc
- 3.41.2.2
+ ${sqlite.jdbc.version}
joda-time
joda-time
- 2.9.9
+ ${joda.time.version}
com.google.oauth-client
google-oauth-client
- 1.34.1
+ ${google.oauth.client.version}
com.google.http-client
google-http-client
- 1.23.0
+ ${google.http.client.version}
com.google.http-client
google-http-client-gson
- 1.23.0
+ ${google.http.client.version}
org.apache.commons
commons-lang3
- 3.12.0
+ ${commons.lang3.version}
ch.qos.logback
logback-classic
- 1.2.3
+ ${logback.classic.version}
org.mock-server
mockserver-netty
- 5.12.0
+ ${mockserver.version}
test
org.mock-server
mockserver-junit-rule
- 5.12.0
+ ${mockserver.version}
test
org.mockito
mockito-core
- 3.11.1
+ ${mockito.version}
test
com.amazonaws
aws-java-sdk
- 1.11.274
+ ${aws.java.sdk.version}
jakarta.xml.bind
jakarta.xml.bind-api
- 2.3.2
+ ${jakarta.xml.bind.api.version}
org.glassfish.jaxb
jaxb-runtime
- 2.3.2
+ ${jaxb.runtime.version}
org.apache.httpcomponents
httpclient
- 4.5.14
+ ${httpclient.version}
commons-io
commons-io
- 2.10.0
+ ${commons.io.version}
org.apache.commons
commons-compress
- 1.24.0
+ ${commons.compress.version}
io.prometheus
simpleclient
- 0.10.0
+ ${simpleclient.version}
io.prometheus
simpleclient_hotspot
- 0.10.0
+ ${simpleclient.version}
io.prometheus
simpleclient_servlet
- 0.10.0
+ ${simpleclient.version}
diff --git a/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/Main.java b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/Main.java
index f56a3a80e3..5e365b893b 100644
--- a/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/Main.java
+++ b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/Main.java
@@ -1,17 +1,14 @@
package uk.ac.ic.wlgitbridge;
+import java.util.Arrays;
import uk.ac.ic.wlgitbridge.application.GitBridgeApp;
-import uk.ac.ic.wlgitbridge.bridge.Bridge;
-import uk.ac.ic.wlgitbridge.server.GitBridgeServer;
import uk.ac.ic.wlgitbridge.util.Log;
-import java.util.Arrays;
-
-/**
+/*
* Created by Winston on 01/11/14.
*/
-/**
+/*
* This is the entry point into the Git Bridge.
*
* It is responsible for creating the {@link GitBridgeApp} and then running it.
@@ -29,21 +26,14 @@ import java.util.Arrays;
*/
public class Main {
- public static void main(String[] args) {
- Log.info(
- "Git Bridge started with args: "
- + Arrays.toString(args)
- );
- try {
- new GitBridgeApp(args).run();
- } catch (Throwable t) {
- /* So that we get a timestamp */
- Log.error(
- "Fatal exception thrown to top level, exiting: ",
- t
- );
- System.exit(1);
- }
+ public static void main(String[] args) {
+ Log.info("Git Bridge started with args: " + Arrays.toString(args));
+ try {
+ new GitBridgeApp(args).run();
+ } catch (Throwable t) {
+ /* So that we get a timestamp */
+ Log.error("Fatal exception thrown to top level, exiting: ", t);
+ System.exit(1);
}
-
+ }
}
diff --git a/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/application/GitBridgeApp.java b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/application/GitBridgeApp.java
index a184effde4..e3cb95226d 100644
--- a/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/application/GitBridgeApp.java
+++ b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/application/GitBridgeApp.java
@@ -1,102 +1,93 @@
package uk.ac.ic.wlgitbridge.application;
+import java.io.IOException;
+import javax.servlet.ServletException;
import uk.ac.ic.wlgitbridge.application.config.Config;
import uk.ac.ic.wlgitbridge.application.exception.ArgsException;
import uk.ac.ic.wlgitbridge.application.exception.ConfigFileException;
import uk.ac.ic.wlgitbridge.server.GitBridgeServer;
import uk.ac.ic.wlgitbridge.util.Log;
-import javax.servlet.ServletException;
-import java.io.IOException;
-
-/**
+/*
* Created by Winston on 02/11/14.
*/
-/**
+/*
* Class that represents the application. Parses arguments and gives them to the
* server, or dies with a usage message.
*/
public class GitBridgeApp implements Runnable {
- public static final int EXIT_CODE_FAILED = 1;
- private static final String USAGE_MESSAGE =
- "usage: writelatex-git-bridge [config_file]";
+ public static final int EXIT_CODE_FAILED = 1;
+ private static final String USAGE_MESSAGE = "usage: writelatex-git-bridge [config_file]";
- private String configFilePath;
- Config config;
- private GitBridgeServer server;
+ private String configFilePath;
+ Config config;
+ private GitBridgeServer server;
- /**
- * Constructs an instance of the WriteLatex-Git Bridge application.
- * @param args args from main, which should be in the format [config_file]
- */
- public GitBridgeApp(String[] args) {
- try {
- parseArguments(args);
- loadConfigFile();
- Log.info("Config loaded: {}", config.getSanitisedString());
- } catch (ArgsException e) {
- printUsage();
- System.exit(EXIT_CODE_FAILED);
- } catch (ConfigFileException e) {
- Log.error(
- "The property for " +
- e.getMissingMember() +
- " is invalid. Check your config file."
- );
- System.exit(EXIT_CODE_FAILED);
- } catch (IOException e) {
- Log.error("Invalid config file. Check the file path.");
- System.exit(EXIT_CODE_FAILED);
- }
- try {
- server = new GitBridgeServer(config);
- } catch (ServletException e) {
- Log.error(
- "Servlet exception when instantiating GitBridgeServer",
- e
- );
- }
+ /*
+ * Constructs an instance of the WriteLatex-Git Bridge application.
+ * @param args args from main, which should be in the format [config_file]
+ */
+ public GitBridgeApp(String[] args) {
+ try {
+ parseArguments(args);
+ loadConfigFile();
+ Log.info("Config loaded: {}", config.getSanitisedString());
+ } catch (ArgsException e) {
+ printUsage();
+ System.exit(EXIT_CODE_FAILED);
+ } catch (ConfigFileException e) {
+ Log.error(
+ "The property for " + e.getMissingMember() + " is invalid. Check your config file.");
+ System.exit(EXIT_CODE_FAILED);
+ } catch (IOException e) {
+ Log.error("Invalid config file. Check the file path.");
+ System.exit(EXIT_CODE_FAILED);
}
-
- /**
- * Starts the server with the port number and root directory path given in
- * the command-line arguments.
- */
- @Override
- public void run() {
- server.start();
+ try {
+ server = new GitBridgeServer(config);
+ } catch (ServletException e) {
+ Log.error("Servlet exception when instantiating GitBridgeServer", e);
}
+ }
- public void stop() {
- server.stop();
+ /*
+ * Starts the server with the port number and root directory path given in
+ * the command-line arguments.
+ */
+ @Override
+ public void run() {
+ server.start();
+ }
+
+ public void stop() {
+ server.stop();
+ }
+
+ /* Helper methods */
+
+ private void parseArguments(String[] args) throws ArgsException {
+ checkArgumentsLength(args);
+ parseConfigFilePath(args);
+ }
+
+ private void checkArgumentsLength(String[] args) throws ArgsException {
+ if (args.length < 1) {
+ throw new ArgsException();
}
+ }
- /* Helper methods */
+ private void parseConfigFilePath(String[] args) throws ArgsException {
+ configFilePath = args[0];
+ }
- private void parseArguments(String[] args) throws ArgsException {
- checkArgumentsLength(args);
- parseConfigFilePath(args);
- }
-
- private void checkArgumentsLength(String[] args) throws ArgsException {
- if (args.length < 1) {
- throw new ArgsException();
- }
- }
-
- private void parseConfigFilePath(String[] args) throws ArgsException {
- configFilePath = args[0];
- }
-
- private void loadConfigFile() throws ConfigFileException, IOException {
- Log.info("Loading config file at path: " + configFilePath);
- config = new Config(configFilePath);
- }
-
- private void printUsage() {
- System.err.println(USAGE_MESSAGE);
- }
+ private void loadConfigFile() throws ConfigFileException, IOException {
+ Log.info("Loading config file at path: " + configFilePath);
+ config = new Config(configFilePath);
+ }
+ private void printUsage() {
+ System.err.println(USAGE_MESSAGE);
+ }
}
diff --git a/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/application/config/Config.java b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/application/config/Config.java
index af1850188d..cf36916600 100644
--- a/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/application/config/Config.java
+++ b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/application/config/Config.java
@@ -3,6 +3,11 @@ package uk.ac.ic.wlgitbridge.application.config;
import com.google.gson.Gson;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
+import java.io.FileReader;
+import java.io.IOException;
+import java.io.Reader;
+import java.util.Optional;
+import javax.annotation.Nullable;
import uk.ac.ic.wlgitbridge.application.exception.ConfigFileException;
import uk.ac.ic.wlgitbridge.bridge.repo.RepoStoreConfig;
import uk.ac.ic.wlgitbridge.bridge.swap.job.SwapJobConfig;
@@ -10,211 +15,182 @@ import uk.ac.ic.wlgitbridge.bridge.swap.store.SwapStoreConfig;
import uk.ac.ic.wlgitbridge.snapshot.base.JSONSource;
import uk.ac.ic.wlgitbridge.util.Instance;
-import javax.annotation.Nullable;
-import java.io.FileReader;
-import java.io.IOException;
-import java.io.Reader;
-import java.util.Optional;
-
-/**
+/*
* Created by Winston on 05/12/14.
*/
public class Config implements JSONSource {
- static Config asSanitised(Config config) {
- return new Config(
- config.port,
- config.bindIp,
- config.idleTimeout,
- config.rootGitDirectory,
- config.apiBaseURL,
- config.postbackURL,
- config.serviceName,
- Oauth2.asSanitised(config.oauth2),
- config.userPasswordEnabled,
- config.repoStore,
- SwapStoreConfig.sanitisedCopy(config.swapStore),
- config.swapJob,
- config.sqliteHeapLimitBytes
- );
+ static Config asSanitised(Config config) {
+ return new Config(
+ config.port,
+ config.bindIp,
+ config.idleTimeout,
+ config.rootGitDirectory,
+ config.apiBaseURL,
+ config.postbackURL,
+ config.serviceName,
+ Oauth2.asSanitised(config.oauth2),
+ config.userPasswordEnabled,
+ config.repoStore,
+ SwapStoreConfig.sanitisedCopy(config.swapStore),
+ config.swapJob,
+ config.sqliteHeapLimitBytes);
+ }
+
+ private int port;
+ private String bindIp;
+ private int idleTimeout;
+ private String rootGitDirectory;
+ private String apiBaseURL;
+ private String postbackURL;
+ private String serviceName;
+ @Nullable private Oauth2 oauth2;
+ private boolean userPasswordEnabled;
+ @Nullable private RepoStoreConfig repoStore;
+ @Nullable private SwapStoreConfig swapStore;
+ @Nullable private SwapJobConfig swapJob;
+ private int sqliteHeapLimitBytes = 0;
+
+ public Config(String configFilePath) throws ConfigFileException, IOException {
+ this(new FileReader(configFilePath));
+ }
+
+ Config(Reader reader) {
+ fromJSON(new Gson().fromJson(reader, JsonElement.class));
+ }
+
+ public Config(
+ int port,
+ String bindIp,
+ int idleTimeout,
+ String rootGitDirectory,
+ String apiBaseURL,
+ String postbackURL,
+ String serviceName,
+ Oauth2 oauth2,
+ boolean userPasswordEnabled,
+ RepoStoreConfig repoStore,
+ SwapStoreConfig swapStore,
+ SwapJobConfig swapJob,
+ int sqliteHeapLimitBytes) {
+ this.port = port;
+ this.bindIp = bindIp;
+ this.idleTimeout = idleTimeout;
+ this.rootGitDirectory = rootGitDirectory;
+ this.apiBaseURL = apiBaseURL;
+ this.postbackURL = postbackURL;
+ this.serviceName = serviceName;
+ this.oauth2 = oauth2;
+ this.userPasswordEnabled = userPasswordEnabled;
+ this.repoStore = repoStore;
+ this.swapStore = swapStore;
+ this.swapJob = swapJob;
+ this.sqliteHeapLimitBytes = sqliteHeapLimitBytes;
+ }
+
+ @Override
+ public void fromJSON(JsonElement json) {
+ JsonObject configObject = json.getAsJsonObject();
+ port = getElement(configObject, "port").getAsInt();
+ bindIp = getElement(configObject, "bindIp").getAsString();
+ idleTimeout = getElement(configObject, "idleTimeout").getAsInt();
+ rootGitDirectory = getElement(configObject, "rootGitDirectory").getAsString();
+ String apiBaseURL = getElement(configObject, "apiBaseUrl").getAsString();
+ if (!apiBaseURL.endsWith("/")) {
+ apiBaseURL += "/";
}
-
- private int port;
- private String bindIp;
- private int idleTimeout;
- private String rootGitDirectory;
- private String apiBaseURL;
- private String postbackURL;
- private String serviceName;
- @Nullable
- private Oauth2 oauth2;
- private boolean userPasswordEnabled;
- @Nullable
- private RepoStoreConfig repoStore;
- @Nullable
- private SwapStoreConfig swapStore;
- @Nullable
- private SwapJobConfig swapJob;
- private int sqliteHeapLimitBytes = 0;
-
- public Config(
- String configFilePath
- ) throws ConfigFileException,
- IOException {
- this(new FileReader(configFilePath));
+ this.apiBaseURL = apiBaseURL;
+ serviceName = getElement(configObject, "serviceName").getAsString();
+ postbackURL = getElement(configObject, "postbackBaseUrl").getAsString();
+ if (!postbackURL.endsWith("/")) {
+ postbackURL += "/";
}
-
- Config(Reader reader) {
- fromJSON(new Gson().fromJson(reader, JsonElement.class));
+ oauth2 = new Gson().fromJson(configObject.get("oauth2"), Oauth2.class);
+ userPasswordEnabled = getOptionalString(configObject, "userPasswordEnabled").equals("true");
+ repoStore = new Gson().fromJson(configObject.get("repoStore"), RepoStoreConfig.class);
+ swapStore = new Gson().fromJson(configObject.get("swapStore"), SwapStoreConfig.class);
+ swapJob = new Gson().fromJson(configObject.get("swapJob"), SwapJobConfig.class);
+ if (configObject.has("sqliteHeapLimitBytes")) {
+ sqliteHeapLimitBytes = getElement(configObject, "sqliteHeapLimitBytes").getAsInt();
}
+ }
- public Config(
- int port,
- String bindIp,
- int idleTimeout,
- String rootGitDirectory,
- String apiBaseURL,
- String postbackURL,
- String serviceName,
- Oauth2 oauth2,
- boolean userPasswordEnabled,
- RepoStoreConfig repoStore,
- SwapStoreConfig swapStore,
- SwapJobConfig swapJob,
- int sqliteHeapLimitBytes
- ) {
- this.port = port;
- this.bindIp = bindIp;
- this.idleTimeout = idleTimeout;
- this.rootGitDirectory = rootGitDirectory;
- this.apiBaseURL = apiBaseURL;
- this.postbackURL = postbackURL;
- this.serviceName = serviceName;
- this.oauth2 = oauth2;
- this.userPasswordEnabled = userPasswordEnabled;
- this.repoStore = repoStore;
- this.swapStore = swapStore;
- this.swapJob = swapJob;
- this.sqliteHeapLimitBytes = sqliteHeapLimitBytes;
+ public String getSanitisedString() {
+ return Instance.prettyGson.toJson(Config.asSanitised(this));
+ }
+
+ public int getPort() {
+ return port;
+ }
+
+ public String getBindIp() {
+ return bindIp;
+ }
+
+ public int getIdleTimeout() {
+ return idleTimeout;
+ }
+
+ public String getRootGitDirectory() {
+ return rootGitDirectory;
+ }
+
+ public int getSqliteHeapLimitBytes() {
+ return this.sqliteHeapLimitBytes;
+ }
+
+ public String getAPIBaseURL() {
+ return apiBaseURL;
+ }
+
+ public String getServiceName() {
+ return serviceName;
+ }
+
+ public String getPostbackURL() {
+ return postbackURL;
+ }
+
+ public boolean isUsingOauth2() {
+ return oauth2 != null;
+ }
+
+ public boolean isUserPasswordEnabled() {
+ return userPasswordEnabled;
+ }
+
+ public Oauth2 getOauth2() {
+ if (!isUsingOauth2()) {
+ throw new AssertionError("Getting oauth2 when not using it");
}
+ return oauth2;
+ }
- @Override
- public void fromJSON(JsonElement json) {
- JsonObject configObject = json.getAsJsonObject();
- port = getElement(configObject, "port").getAsInt();
- bindIp = getElement(configObject, "bindIp").getAsString();
- idleTimeout = getElement(configObject, "idleTimeout").getAsInt();
- rootGitDirectory = getElement(
- configObject,
- "rootGitDirectory"
- ).getAsString();
- String apiBaseURL = getElement(
- configObject,
- "apiBaseUrl"
- ).getAsString();
- if (!apiBaseURL.endsWith("/")) {
- apiBaseURL += "/";
- }
- this.apiBaseURL = apiBaseURL;
- serviceName = getElement(configObject, "serviceName").getAsString();
- postbackURL = getElement(configObject, "postbackBaseUrl").getAsString();
- if (!postbackURL.endsWith("/")) {
- postbackURL += "/";
- }
- oauth2 = new Gson().fromJson(configObject.get("oauth2"), Oauth2.class);
- userPasswordEnabled = getOptionalString(configObject, "userPasswordEnabled").equals("true");
- repoStore = new Gson().fromJson(
- configObject.get("repoStore"), RepoStoreConfig.class);
- swapStore = new Gson().fromJson(
- configObject.get("swapStore"),
- SwapStoreConfig.class
- );
- swapJob = new Gson().fromJson(
- configObject.get("swapJob"),
- SwapJobConfig.class
- );
- if (configObject.has("sqliteHeapLimitBytes")) {
- sqliteHeapLimitBytes = getElement(configObject, "sqliteHeapLimitBytes").getAsInt();
- }
+ public Optional getRepoStore() {
+ return Optional.ofNullable(repoStore);
+ }
+
+ public Optional getSwapStore() {
+ return Optional.ofNullable(swapStore);
+ }
+
+ public Optional getSwapJob() {
+ return Optional.ofNullable(swapJob);
+ }
+
+ private JsonElement getElement(JsonObject configObject, String name) {
+ JsonElement element = configObject.get(name);
+ if (element == null) {
+ throw new RuntimeException(new ConfigFileException(name));
}
+ return element;
+ }
- public String getSanitisedString() {
- return Instance.prettyGson.toJson(Config.asSanitised(this));
+ private String getOptionalString(JsonObject configObject, String name) {
+ JsonElement element = configObject.get(name);
+ if (element == null || !element.isJsonPrimitive()) {
+ return "";
}
-
- public int getPort() {
- return port;
- }
-
- public String getBindIp() {
- return bindIp;
- }
-
- public int getIdleTimeout() {
- return idleTimeout;
- }
-
- public String getRootGitDirectory() {
- return rootGitDirectory;
- }
-
- public int getSqliteHeapLimitBytes() {
- return this.sqliteHeapLimitBytes;
- }
-
- public String getAPIBaseURL() {
- return apiBaseURL;
- }
-
- public String getServiceName() {
- return serviceName;
- }
-
- public String getPostbackURL() {
- return postbackURL;
- }
-
- public boolean isUsingOauth2() {
- return oauth2 != null;
- }
-
- public boolean isUserPasswordEnabled() {
- return userPasswordEnabled;
- }
-
- public Oauth2 getOauth2() {
- if (!isUsingOauth2()) {
- throw new AssertionError("Getting oauth2 when not using it");
- }
- return oauth2;
- }
-
- public Optional getRepoStore() {
- return Optional.ofNullable(repoStore);
- }
-
- public Optional getSwapStore() {
- return Optional.ofNullable(swapStore);
- }
-
- public Optional getSwapJob() {
- return Optional.ofNullable(swapJob);
- }
-
- private JsonElement getElement(JsonObject configObject, String name) {
- JsonElement element = configObject.get(name);
- if (element == null) {
- throw new RuntimeException(new ConfigFileException(name));
- }
- return element;
- }
-
- private String getOptionalString(JsonObject configObject, String name) {
- JsonElement element = configObject.get(name);
- if (element == null || !element.isJsonPrimitive()) {
- return "";
- }
- return element.getAsString();
- }
-
+ return element.getAsString();
+ }
}
diff --git a/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/application/config/Oauth2.java b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/application/config/Oauth2.java
index daf1170c82..1db7d3b4d2 100644
--- a/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/application/config/Oauth2.java
+++ b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/application/config/Oauth2.java
@@ -1,42 +1,33 @@
package uk.ac.ic.wlgitbridge.application.config;
-/**
+/*
* Created by winston on 25/10/15.
*/
public class Oauth2 {
- private final String oauth2ClientID;
- private final String oauth2ClientSecret;
- private final String oauth2Server;
+ private final String oauth2ClientID;
+ private final String oauth2ClientSecret;
+ private final String oauth2Server;
- public Oauth2(
- String oauth2ClientID,
- String oauth2ClientSecret,
- String oauth2Server
- ) {
- this.oauth2ClientID = oauth2ClientID;
- this.oauth2ClientSecret = oauth2ClientSecret;
- this.oauth2Server = oauth2Server;
- }
+ public Oauth2(String oauth2ClientID, String oauth2ClientSecret, String oauth2Server) {
+ this.oauth2ClientID = oauth2ClientID;
+ this.oauth2ClientSecret = oauth2ClientSecret;
+ this.oauth2Server = oauth2Server;
+ }
- public String getOauth2ClientID() {
- return oauth2ClientID;
- }
+ public String getOauth2ClientID() {
+ return oauth2ClientID;
+ }
- public String getOauth2ClientSecret() {
- return oauth2ClientSecret;
- }
+ public String getOauth2ClientSecret() {
+ return oauth2ClientSecret;
+ }
- public String getOauth2Server() {
- return oauth2Server;
- }
-
- public static Oauth2 asSanitised(Oauth2 oauth2) {
- return new Oauth2(
- "",
- "",
- oauth2.oauth2Server
- );
- }
+ public String getOauth2Server() {
+ return oauth2Server;
+ }
+ public static Oauth2 asSanitised(Oauth2 oauth2) {
+ return new Oauth2("", "", oauth2.oauth2Server);
+ }
}
diff --git a/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/application/exception/ArgsException.java b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/application/exception/ArgsException.java
index 9557c35f29..5717aff89f 100644
--- a/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/application/exception/ArgsException.java
+++ b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/application/exception/ArgsException.java
@@ -1,6 +1,6 @@
package uk.ac.ic.wlgitbridge.application.exception;
-/**
+/*
* Created by Winston on 03/11/14.
*/
public class ArgsException extends Exception {}
diff --git a/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/application/exception/ConfigFileException.java b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/application/exception/ConfigFileException.java
index bbe9671dc2..8e6ac7dbed 100644
--- a/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/application/exception/ConfigFileException.java
+++ b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/application/exception/ConfigFileException.java
@@ -1,18 +1,17 @@
package uk.ac.ic.wlgitbridge.application.exception;
-/**
+/*
* Created by Winston on 05/12/14.
*/
public class ConfigFileException extends Exception {
- private final String missingMember;
+ private final String missingMember;
- public ConfigFileException(String missingMember) {
- this.missingMember = missingMember;
- }
-
- public String getMissingMember() {
- return missingMember;
- }
+ public ConfigFileException(String missingMember) {
+ this.missingMember = missingMember;
+ }
+ public String getMissingMember() {
+ return missingMember;
+ }
}
diff --git a/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/application/jetty/NullLogger.java b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/application/jetty/NullLogger.java
index e996bd50c3..4543a59ee0 100644
--- a/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/application/jetty/NullLogger.java
+++ b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/application/jetty/NullLogger.java
@@ -2,84 +2,59 @@ package uk.ac.ic.wlgitbridge.application.jetty;
import org.eclipse.jetty.util.log.Logger;
-/**
+/*
* Created by Winston on 03/11/14.
*/
public class NullLogger implements Logger {
- @Override
- public String getName() {
- return "null_logger";
- }
+ @Override
+ public String getName() {
+ return "null_logger";
+ }
- @Override
- public void warn(String s, Object... objects) {
+ @Override
+ public void warn(String s, Object... objects) {}
- }
+ @Override
+ public void warn(Throwable throwable) {}
- @Override
- public void warn(Throwable throwable) {
+ @Override
+ public void warn(String s, Throwable throwable) {}
- }
+ @Override
+ public void info(String s, Object... objects) {}
- @Override
- public void warn(String s, Throwable throwable) {
+ @Override
+ public void info(Throwable throwable) {}
- }
+ @Override
+ public void info(String s, Throwable throwable) {}
- @Override
- public void info(String s, Object... objects) {
+ @Override
+ public boolean isDebugEnabled() {
+ return false;
+ }
- }
+ @Override
+ public void setDebugEnabled(boolean b) {}
- @Override
- public void info(Throwable throwable) {
+ @Override
+ public void debug(String s, Object... objects) {}
- }
+ @Override
+ public void debug(String s, long l) {}
- @Override
- public void info(String s, Throwable throwable) {
+ @Override
+ public void debug(Throwable throwable) {}
- }
+ @Override
+ public void debug(String s, Throwable throwable) {}
- @Override
- public boolean isDebugEnabled() {
- return false;
- }
-
- @Override
- public void setDebugEnabled(boolean b) {
-
- }
-
- @Override
- public void debug(String s, Object... objects) {
-
- }
-
- @Override
- public void debug(String s, long l) {
-
- }
-
- @Override
- public void debug(Throwable throwable) {
-
- }
-
- @Override
- public void debug(String s, Throwable throwable) {
-
- }
-
- @Override
- public Logger getLogger(String s) {
- return this;
- }
-
- @Override
- public void ignore(Throwable throwable) {
-
- }
+ @Override
+ public Logger getLogger(String s) {
+ return this;
+ }
+ @Override
+ public void ignore(Throwable throwable) {}
}
diff --git a/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/Bridge.java b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/Bridge.java
index f448024e9a..83fbedadaf 100644
--- a/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/Bridge.java
+++ b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/Bridge.java
@@ -1,11 +1,15 @@
package uk.ac.ic.wlgitbridge.bridge;
import com.google.api.client.auth.oauth2.Credential;
+import java.io.File;
+import java.io.IOException;
+import java.sql.Timestamp;
+import java.time.LocalDateTime;
+import java.util.*;
import org.eclipse.jgit.errors.RepositoryNotFoundException;
import uk.ac.ic.wlgitbridge.application.config.Config;
import uk.ac.ic.wlgitbridge.bridge.db.DBStore;
import uk.ac.ic.wlgitbridge.bridge.db.ProjectState;
-import uk.ac.ic.wlgitbridge.bridge.db.sqlite.SqliteDBStore;
import uk.ac.ic.wlgitbridge.bridge.gc.GcJob;
import uk.ac.ic.wlgitbridge.bridge.gc.GcJobImpl;
import uk.ac.ic.wlgitbridge.bridge.lock.LockGuard;
@@ -13,12 +17,9 @@ import uk.ac.ic.wlgitbridge.bridge.lock.ProjectLock;
import uk.ac.ic.wlgitbridge.bridge.repo.*;
import uk.ac.ic.wlgitbridge.bridge.resource.ResourceCache;
import uk.ac.ic.wlgitbridge.bridge.resource.UrlResourceCache;
-import uk.ac.ic.wlgitbridge.bridge.snapshot.NetSnapshotApi;
import uk.ac.ic.wlgitbridge.bridge.snapshot.SnapshotApi;
import uk.ac.ic.wlgitbridge.bridge.snapshot.SnapshotApiFacade;
import uk.ac.ic.wlgitbridge.bridge.swap.job.SwapJob;
-import uk.ac.ic.wlgitbridge.bridge.swap.job.SwapJobImpl;
-import uk.ac.ic.wlgitbridge.bridge.swap.store.S3SwapStore;
import uk.ac.ic.wlgitbridge.bridge.swap.store.SwapStore;
import uk.ac.ic.wlgitbridge.data.CandidateSnapshot;
import uk.ac.ic.wlgitbridge.data.CannotAcquireLockException;
@@ -27,33 +28,19 @@ import uk.ac.ic.wlgitbridge.data.filestore.GitDirectoryContents;
import uk.ac.ic.wlgitbridge.data.filestore.RawDirectory;
import uk.ac.ic.wlgitbridge.data.filestore.RawFile;
import uk.ac.ic.wlgitbridge.data.model.Snapshot;
+import uk.ac.ic.wlgitbridge.git.exception.FileLimitExceededException;
import uk.ac.ic.wlgitbridge.git.exception.GitUserException;
import uk.ac.ic.wlgitbridge.git.exception.SizeLimitExceededException;
-import uk.ac.ic.wlgitbridge.git.exception.FileLimitExceededException;
-import uk.ac.ic.wlgitbridge.git.handler.WLReceivePackFactory;
-import uk.ac.ic.wlgitbridge.git.handler.WLRepositoryResolver;
-import uk.ac.ic.wlgitbridge.git.handler.WLUploadPackFactory;
-import uk.ac.ic.wlgitbridge.git.handler.hook.WriteLatexPutHook;
-import uk.ac.ic.wlgitbridge.server.FileHandler;
-import uk.ac.ic.wlgitbridge.server.PostbackContents;
-import uk.ac.ic.wlgitbridge.server.PostbackHandler;
-import uk.ac.ic.wlgitbridge.snapshot.base.MissingRepositoryException;
import uk.ac.ic.wlgitbridge.snapshot.base.ForbiddenException;
+import uk.ac.ic.wlgitbridge.snapshot.base.MissingRepositoryException;
import uk.ac.ic.wlgitbridge.snapshot.getdoc.GetDocResult;
import uk.ac.ic.wlgitbridge.snapshot.getforversion.SnapshotAttachment;
import uk.ac.ic.wlgitbridge.snapshot.push.PostbackManager;
-import uk.ac.ic.wlgitbridge.snapshot.push.PostbackPromise;
import uk.ac.ic.wlgitbridge.snapshot.push.PushResult;
import uk.ac.ic.wlgitbridge.snapshot.push.exception.*;
import uk.ac.ic.wlgitbridge.util.Log;
-import java.io.File;
-import java.io.IOException;
-import java.sql.Timestamp;
-import java.time.LocalDateTime;
-import java.util.*;
-
-/**
+/*
* This is the heart of the Git Bridge. You plug in all the parts (project
* lock, repo store, db store, swap store, snapshot api, resource cache and
* postback manager) is called by Git user requests and Overleaf postback
@@ -66,7 +53,7 @@ import java.util.*;
* @see WLRepositoryResolver - used on all requests associate a repo with a
* project name, or fail
*
-* @see WLUploadPackFactory - used to handle clones and fetches
+ * @see WLUploadPackFactory - used to handle clones and fetches
*
* @see WLReceivePackFactory - used to handle pushes by setting a hook
* @see WriteLatexPutHook - the hook used to handle pushes
@@ -141,683 +128,582 @@ import java.util.*;
*/
public class Bridge {
- private final Config config;
+ private final Config config;
- private final ProjectLock lock;
+ private final ProjectLock lock;
- private final RepoStore repoStore;
- private final DBStore dbStore;
- private final SwapStore swapStore;
- private final SwapJob swapJob;
- private final GcJob gcJob;
+ private final RepoStore repoStore;
+ private final DBStore dbStore;
+ private final SwapStore swapStore;
+ private final SwapJob swapJob;
+ private final GcJob gcJob;
- private final SnapshotApiFacade snapshotAPI;
- private final ResourceCache resourceCache;
+ private final SnapshotApiFacade snapshotAPI;
+ private final ResourceCache resourceCache;
- private final PostbackManager postbackManager;
+ private final PostbackManager postbackManager;
- /**
- * Creates a Bridge from its configurable parts, which are the repo, db and
- * swap store, and the swap job config.
- *
- * This should be the method used to create a Bridge.
- * @param config The config to use
- * @param repoStore The repo store to use
- * @param dbStore The db store to use
- * @param swapStore The swap store to use
- * @param snapshotApi The snapshot api to use
- * @return The constructed Bridge.
- */
- public static Bridge make(
- Config config,
- RepoStore repoStore,
- DBStore dbStore,
- SwapStore swapStore,
- SnapshotApi snapshotApi
- ) {
- ProjectLock lock = new ProjectLockImpl((int threads) ->
- Log.info("Waiting for " + threads + " projects...")
- );
- return new Bridge(
- config,
- lock,
- repoStore,
- dbStore,
- swapStore,
- SwapJob.fromConfig(
- config.getSwapJob(),
- lock,
- repoStore,
- dbStore,
- swapStore
- ),
- new GcJobImpl(repoStore, lock),
- new SnapshotApiFacade(snapshotApi),
- new UrlResourceCache(dbStore)
- );
+ /*
+ * Creates a Bridge from its configurable parts, which are the repo, db and
+ * swap store, and the swap job config.
+ *
+ * This should be the method used to create a Bridge.
+ * @param config The config to use
+ * @param repoStore The repo store to use
+ * @param dbStore The db store to use
+ * @param swapStore The swap store to use
+ * @param snapshotApi The snapshot api to use
+ * @return The constructed Bridge.
+ */
+ public static Bridge make(
+ Config config,
+ RepoStore repoStore,
+ DBStore dbStore,
+ SwapStore swapStore,
+ SnapshotApi snapshotApi) {
+ ProjectLock lock =
+ new ProjectLockImpl((int threads) -> Log.info("Waiting for " + threads + " projects..."));
+ return new Bridge(
+ config,
+ lock,
+ repoStore,
+ dbStore,
+ swapStore,
+ SwapJob.fromConfig(config.getSwapJob(), lock, repoStore, dbStore, swapStore),
+ new GcJobImpl(repoStore, lock),
+ new SnapshotApiFacade(snapshotApi),
+ new UrlResourceCache(dbStore));
+ }
+
+ /*
+ * Creates a bridge from all of its components, not just its configurable
+ * parts. This is for substituting mock/stub components for testing.
+ * It's also used by Bridge.make to actually construct the bridge.
+ * @param lock the {@link ProjectLock} to use
+ * @param repoStore the {@link RepoStore} to use
+ * @param dbStore the {@link DBStore} to use
+ * @param swapStore the {@link SwapStore} to use
+ * @param swapJob the {@link SwapJob} to use
+ * @param gcJob
+ * @param snapshotAPI the {@link SnapshotApi} to use
+ * @param resourceCache the {@link ResourceCache} to use
+ */
+ Bridge(
+ Config config,
+ ProjectLock lock,
+ RepoStore repoStore,
+ DBStore dbStore,
+ SwapStore swapStore,
+ SwapJob swapJob,
+ GcJob gcJob,
+ SnapshotApiFacade snapshotAPI,
+ ResourceCache resourceCache) {
+ this.config = config;
+ this.lock = lock;
+ this.repoStore = repoStore;
+ this.dbStore = dbStore;
+ this.swapStore = swapStore;
+ this.snapshotAPI = snapshotAPI;
+ this.resourceCache = resourceCache;
+ this.swapJob = swapJob;
+ this.gcJob = gcJob;
+ postbackManager = new PostbackManager();
+ Runtime.getRuntime().addShutdownHook(new Thread(this::doShutdown));
+ repoStore.purgeNonexistentProjects(dbStore.getProjectNames());
+ }
+
+ /*
+ * This performs the graceful shutdown of the Bridge, which is called by the
+ * shutdown hook. It acquires the project write lock, which prevents
+ * work being done for new projects (which acquire the read lock).
+ * Once it has the write lock, there are no readers left, so the git bridge
+ * can shut down gracefully.
+ *
+ * It is also used by the tests.
+ */
+ void doShutdown() {
+ Log.info("Shutdown received.");
+ Log.info("Stopping SwapJob");
+ swapJob.stop();
+ Log.info("Stopping GcJob");
+ gcJob.stop();
+ Log.info("Waiting for projects");
+ lock.lockAll();
+ Log.info("Bye");
+ }
+
+ /*
+ * Starts the swap job, which will begin checking whether projects should be
+ * swapped with a configurable frequency.
+ */
+ public void startBackgroundJobs() {
+ swapJob.start();
+ gcJob.start();
+ }
+
+ public boolean healthCheck() {
+ try {
+ dbStore.getNumProjects();
+ File rootDirectory = new File("/");
+ if (!rootDirectory.exists()) {
+ throw new Exception("bad filesystem state, root directory does not exist");
+ }
+ Log.debug("[HealthCheck] passed");
+ return true;
+ } catch (Exception e) {
+ Log.error("[HealthCheck] FAILED!", e);
+ return false;
}
+ }
- /**
- * Creates a bridge from all of its components, not just its configurable
- * parts. This is for substituting mock/stub components for testing.
- * It's also used by Bridge.make to actually construct the bridge.
- * @param lock the {@link ProjectLock} to use
- * @param repoStore the {@link RepoStore} to use
- * @param dbStore the {@link DBStore} to use
- * @param swapStore the {@link SwapStore} to use
- * @param swapJob the {@link SwapJob} to use
- * @param gcJob
- * @param snapshotAPI the {@link SnapshotApi} to use
- * @param resourceCache the {@link ResourceCache} to use
- */
- Bridge(
- Config config,
- ProjectLock lock,
- RepoStore repoStore,
- DBStore dbStore,
- SwapStore swapStore,
- SwapJob swapJob,
- GcJob gcJob,
- SnapshotApiFacade snapshotAPI,
- ResourceCache resourceCache
- ) {
- this.config = config;
- this.lock = lock;
- this.repoStore = repoStore;
- this.dbStore = dbStore;
- this.swapStore = swapStore;
- this.snapshotAPI = snapshotAPI;
- this.resourceCache = resourceCache;
- this.swapJob = swapJob;
- this.gcJob = gcJob;
- postbackManager = new PostbackManager();
- Runtime.getRuntime().addShutdownHook(new Thread(this::doShutdown));
- repoStore.purgeNonexistentProjects(dbStore.getProjectNames());
- }
-
- /**
- * This performs the graceful shutdown of the Bridge, which is called by the
- * shutdown hook. It acquires the project write lock, which prevents
- * work being done for new projects (which acquire the read lock).
- * Once it has the write lock, there are no readers left, so the git bridge
- * can shut down gracefully.
- *
- * It is also used by the tests.
- */
- void doShutdown() {
- Log.info("Shutdown received.");
- Log.info("Stopping SwapJob");
- swapJob.stop();
- Log.info("Stopping GcJob");
- gcJob.stop();
- Log.info("Waiting for projects");
- lock.lockAll();
- Log.info("Bye");
- }
-
- /**
- * Starts the swap job, which will begin checking whether projects should be
- * swapped with a configurable frequency.
- */
- public void startBackgroundJobs() {
- swapJob.start();
- gcJob.start();
- }
-
- public boolean healthCheck() {
- try {
- dbStore.getNumProjects();
- File rootDirectory = new File("/");
- if (!rootDirectory.exists()) {
- throw new Exception("bad filesystem state, root directory does not exist");
- }
- Log.debug("[HealthCheck] passed");
- return true;
- } catch (Exception e) {
- Log.error("[HealthCheck] FAILED!", e);
- return false;
- }
- }
-
- /**
- * Performs a check of inconsistencies in the DB. This was used to upgrade
- * the schema.
- */
- public void checkDB() {
- Log.info("Checking DB");
- File rootDir = repoStore.getRootDirectory();
- for (File f : rootDir.listFiles()) {
- if (f.getName().equals(".wlgb")) {
- continue;
- }
- String projName = f.getName();
- try (LockGuard __ = lock.lockGuard(projName)) {
- File dotGit = new File(f, ".git");
- if (!dotGit.exists()) {
- Log.warn("Project: {} has no .git", projName);
- continue;
- }
- ProjectState state = dbStore.getProjectState(projName);
- if (state != ProjectState.NOT_PRESENT) {
- continue;
- }
- Log.warn(
- "Project: {} not in swap_store, adding",
- projName
- );
- dbStore.setLastAccessedTime(
- projName,
- new Timestamp(dotGit.lastModified())
- );
- } catch (CannotAcquireLockException e) {
- throw new RuntimeException(e);
- }
+ /*
+ * Performs a check of inconsistencies in the DB. This was used to upgrade
+ * the schema.
+ */
+ public void checkDB() {
+ Log.info("Checking DB");
+ File rootDir = repoStore.getRootDirectory();
+ for (File f : rootDir.listFiles()) {
+ if (f.getName().equals(".wlgb")) {
+ continue;
+ }
+ String projName = f.getName();
+ try (LockGuard __ = lock.lockGuard(projName)) {
+ File dotGit = new File(f, ".git");
+ if (!dotGit.exists()) {
+ Log.warn("Project: {} has no .git", projName);
+ continue;
}
- }
-
- /**
- * Synchronises the given repository with Overleaf.
- *
- * It acquires the project lock and calls
- * {@link #getUpdatedRepoCritical(Optional, String, GetDocResult)}.
- * @param oauth2 The oauth2 to use
- * @param projectName The name of the project
- * @throws IOException
- * @throws GitUserException
- */
- public ProjectRepo getUpdatedRepo(
- Optional oauth2,
- String projectName
- ) throws IOException, GitUserException, CannotAcquireLockException {
- try (LockGuard __ = lock.lockGuard(projectName)) {
- Optional maybeDoc = snapshotAPI.getDoc(oauth2, projectName);
- if (!maybeDoc.isPresent()) {
- throw new RepositoryNotFoundException(projectName);
- }
- GetDocResult doc = maybeDoc.get();
- Log.debug("[{}] Updating repository", projectName);
- return getUpdatedRepoCritical(oauth2, projectName, doc);
+ ProjectState state = dbStore.getProjectState(projName);
+ if (state != ProjectState.NOT_PRESENT) {
+ continue;
}
+ Log.warn("Project: {} not in swap_store, adding", projName);
+ dbStore.setLastAccessedTime(projName, new Timestamp(dotGit.lastModified()));
+ } catch (CannotAcquireLockException e) {
+ throw new RuntimeException(e);
+ }
+ }
+ }
+
+ /*
+ * Synchronises the given repository with Overleaf.
+ *
+ * It acquires the project lock and calls
+ * {@link #getUpdatedRepoCritical(Optional, String, GetDocResult)}.
+ * @param oauth2 The oauth2 to use
+ * @param projectName The name of the project
+ * @throws IOException
+ * @throws GitUserException
+ */
+ public ProjectRepo getUpdatedRepo(Optional oauth2, String projectName)
+ throws IOException, GitUserException, CannotAcquireLockException {
+ try (LockGuard __ = lock.lockGuard(projectName)) {
+ Optional maybeDoc = snapshotAPI.getDoc(oauth2, projectName);
+ if (!maybeDoc.isPresent()) {
+ throw new RepositoryNotFoundException(projectName);
+ }
+ GetDocResult doc = maybeDoc.get();
+ Log.debug("[{}] Updating repository", projectName);
+ return getUpdatedRepoCritical(oauth2, projectName, doc);
+ }
+ }
+
+ /*
+ * Synchronises the given repository with Overleaf.
+ *
+ * Pre: the project lock must be acquired for the given repo.
+ *
+ * 1. Queries the project state for the given project name.
+ * a. NOT_PRESENT = We've never seen it before, and the row for the
+ * project doesn't even exist. The project definitely
+ * exists because we would have aborted otherwise.
+ * b. PRESENT = The project is on disk.
+ * c. SWAPPED = The project is in the {@link SwapStore}
+ *
+ * If the project has never been cloned, it is git init'd. If the project
+ * is in swap, it is restored to disk. Otherwise, the project was already
+ * present.
+ *
+ * With the project present, snapshots are downloaded from the snapshot
+ * API with {@link #updateProject(Optional, ProjectRepo)}.
+ *
+ * Then, the last accessed time of the project is set to the current time.
+ * This is to support the LRU of the swap store.
+ * @param oauth2
+ * @param projectName The name of the project
+ * @throws IOException
+ * @throws GitUserException
+ */
+ private ProjectRepo getUpdatedRepoCritical(
+ Optional oauth2, String projectName, GetDocResult doc)
+ throws IOException, GitUserException {
+ ProjectRepo repo;
+ ProjectState state = dbStore.getProjectState(projectName);
+ switch (state) {
+ case NOT_PRESENT:
+ Log.info("[{}] Repo not present", projectName);
+ repo = repoStore.initRepo(projectName);
+ break;
+ case SWAPPED:
+ swapJob.restore(projectName);
+ repo = repoStore.getExistingRepo(projectName);
+ break;
+ default:
+ repo = repoStore.getExistingRepo(projectName);
+ }
+ updateProject(oauth2, repo);
+ dbStore.setLastAccessedTime(projectName, Timestamp.valueOf(LocalDateTime.now()));
+ return repo;
+ }
+
+ /*
+ * The public call to push a project.
+ *
+ * It acquires the lock and calls {@link #pushCritical(
+ * Optional,
+ * String,
+ * RawDirectory,
+ * RawDirectory
+ * )}, catching exceptions, logging, and rethrowing them.
+ * @param oauth2 The oauth2 to use for the snapshot API
+ * @param projectName The name of the project to push to
+ * @param directoryContents The new contents of the project
+ * @param oldDirectoryContents The old contents of the project
+ * @param hostname
+ * @throws SnapshotPostException
+ * @throws IOException
+ * @throws MissingRepositoryException
+ * @throws ForbiddenException
+ * @throws GitUserException
+ */
+ public void push(
+ Optional oauth2,
+ String projectName,
+ RawDirectory directoryContents,
+ RawDirectory oldDirectoryContents,
+ String hostname)
+ throws SnapshotPostException,
+ IOException,
+ MissingRepositoryException,
+ ForbiddenException,
+ GitUserException,
+ CannotAcquireLockException {
+ Log.debug("[{}] pushing to Overleaf", projectName);
+ try (LockGuard __ = lock.lockGuard(projectName)) {
+ Log.info("[{}] got project lock", projectName);
+ pushCritical(oauth2, projectName, directoryContents, oldDirectoryContents);
+ } catch (SevereSnapshotPostException e) {
+ Log.warn("[" + projectName + "] Failed to put to Overleaf", e);
+ throw e;
+ } catch (SnapshotPostException e) {
+ /* Stack trace should be printed further up */
+ Log.warn(
+ "[{}] Exception when waiting for postback: {}",
+ projectName,
+ e.getClass().getSimpleName());
+ throw e;
+ } catch (IOException e) {
+ Log.warn("[{}] IOException on put: {}", projectName, e);
+ throw e;
}
- /**
- * Synchronises the given repository with Overleaf.
- *
- * Pre: the project lock must be acquired for the given repo.
- *
- * 1. Queries the project state for the given project name.
- * a. NOT_PRESENT = We've never seen it before, and the row for the
- * project doesn't even exist. The project definitely
- * exists because we would have aborted otherwise.
- * b. PRESENT = The project is on disk.
- * c. SWAPPED = The project is in the {@link SwapStore}
- *
- * If the project has never been cloned, it is git init'd. If the project
- * is in swap, it is restored to disk. Otherwise, the project was already
- * present.
- *
- * With the project present, snapshots are downloaded from the snapshot
- * API with {@link #updateProject(Optional, ProjectRepo)}.
- *
- * Then, the last accessed time of the project is set to the current time.
- * This is to support the LRU of the swap store.
- * @param oauth2
- * @param projectName The name of the project
- * @throws IOException
- * @throws GitUserException
- */
- private ProjectRepo getUpdatedRepoCritical(
- Optional oauth2,
- String projectName,
- GetDocResult doc
- ) throws IOException, GitUserException {
- ProjectRepo repo;
- ProjectState state = dbStore.getProjectState(projectName);
- switch (state) {
- case NOT_PRESENT:
- Log.info("[{}] Repo not present", projectName);
- repo = repoStore.initRepo(projectName);
- break;
- case SWAPPED:
- swapJob.restore(projectName);
- repo = repoStore.getExistingRepo(projectName);
- break;
- default:
- repo = repoStore.getExistingRepo(projectName);
- }
- updateProject(oauth2, repo);
- dbStore.setLastAccessedTime(
- projectName,
- Timestamp.valueOf(LocalDateTime.now())
- );
- return repo;
+ gcJob.queueForGc(projectName);
+ }
+
+ /*
+ * Does the work of pushing to a project, assuming the project lock is held.
+ * The {@link WriteLatexPutHook} is the original caller, and when we return
+ * without throwing, the commit is committed.
+ *
+ * We start off by creating a postback key, which is given in the url when
+ * the Overleaf app tries to access the atts.
+ *
+ * Then creates a {@link CandidateSnapshot} from the old and new project
+ * contents. The
+ * {@link CandidateSnapshot} is created using
+ * {@link #createCandidateSnapshot(String, RawDirectory, RawDirectory)},
+ * which creates the snapshot object and writes the push files to the
+ * atts directory, which is served by the {@link PostbackHandler}.
+ * The files are deleted at the end of a try-with-resources block.
+ *
+ * Then 3 things are used to make the push request to the snapshot API:
+ * 1. The oauth2
+ * 2. The candidate snapshot
+ * 3. The postback key
+ *
+ * If the snapshot API reports this as not successful, we immediately throw
+ * an {@link OutOfDateException}, which goes back to the user.
+ *
+ * Otherwise, we wait (with a timeout) on a promise from the postback
+ * manager, which can throw back to the user.
+ *
+ * If this is successful, we approve the snapshot with
+ * {@link #approveSnapshot(int, CandidateSnapshot)}, which updates our side
+ * of the push: the latest version and the URL index store.
+ *
+ * Then, we set the last accessed time for the swap store.
+ *
+ * Finally, after we return, the push to the repo from the hook is
+ * successful and the repo gets updated.
+ *
+ * @param oauth2
+ * @param projectName
+ * @param directoryContents
+ * @param oldDirectoryContents
+ * @throws IOException
+ * @throws MissingRepositoryException
+ * @throws ForbiddenException
+ * @throws SnapshotPostException
+ * @throws GitUserException
+ */
+ private void pushCritical(
+ Optional oauth2,
+ String projectName,
+ RawDirectory directoryContents,
+ RawDirectory oldDirectoryContents)
+ throws IOException,
+ MissingRepositoryException,
+ ForbiddenException,
+ SnapshotPostException,
+ GitUserException {
+ Optional maxFileNum = config.getRepoStore().flatMap(RepoStoreConfig::getMaxFileNum);
+ if (maxFileNum.isPresent()) {
+ long maxFileNum_ = maxFileNum.get();
+ if (directoryContents.getFileTable().size() > maxFileNum_) {
+ Log.warn(
+ "[{}] Too many files: {}/{}",
+ projectName,
+ directoryContents.getFileTable().size(),
+ maxFileNum_);
+ throw new FileLimitExceededException(directoryContents.getFileTable().size(), maxFileNum_);
+ }
}
-
- /**
- * The public call to push a project.
- *
- * It acquires the lock and calls {@link #pushCritical(
- * Optional,
- * String,
- * RawDirectory,
- * RawDirectory
- * )}, catching exceptions, logging, and rethrowing them.
- * @param oauth2 The oauth2 to use for the snapshot API
- * @param projectName The name of the project to push to
- * @param directoryContents The new contents of the project
- * @param oldDirectoryContents The old contents of the project
- * @param hostname
- * @throws SnapshotPostException
- * @throws IOException
- * @throws MissingRepositoryException
- * @throws ForbiddenException
- * @throws GitUserException
- */
- public void push(
- Optional oauth2,
- String projectName,
- RawDirectory directoryContents,
- RawDirectory oldDirectoryContents,
- String hostname
- ) throws SnapshotPostException, IOException, MissingRepositoryException, ForbiddenException, GitUserException, CannotAcquireLockException {
- Log.debug("[{}] pushing to Overleaf", projectName);
- try (LockGuard __ = lock.lockGuard(projectName)) {
- Log.info("[{}] got project lock", projectName);
- pushCritical(
- oauth2,
- projectName,
- directoryContents,
- oldDirectoryContents
- );
- } catch (SevereSnapshotPostException e) {
- Log.warn(
- "[" + projectName + "] Failed to put to Overleaf",
- e
- );
- throw e;
- } catch (SnapshotPostException e) {
- /* Stack trace should be printed further up */
- Log.warn(
- "[{}] Exception when waiting for postback: {}",
- projectName,
- e.getClass().getSimpleName()
- );
- throw e;
- } catch (IOException e) {
- Log.warn("[{}] IOException on put: {}", projectName, e);
- throw e;
- }
-
- gcJob.queueForGc(projectName);
+ Log.debug(
+ "[{}] Pushing files ({} new, {} old)",
+ projectName,
+ directoryContents.getFileTable().size(),
+ oldDirectoryContents.getFileTable().size());
+ String postbackKey = postbackManager.makeKeyForProject(projectName);
+ Log.debug("[{}] Created postback key: {}", projectName, postbackKey);
+ try (CandidateSnapshot candidate =
+ createCandidateSnapshot(projectName, directoryContents, oldDirectoryContents); ) {
+ Log.debug("[{}] Candidate snapshot created: {}", projectName, candidate);
+ PushResult result = snapshotAPI.push(oauth2, candidate, postbackKey);
+ if (result.wasSuccessful()) {
+ Log.debug("[{}] Push to Overleaf successful", projectName);
+ Log.debug("[{}] Waiting for postback...", projectName);
+ int versionID = postbackManager.waitForVersionIdOrThrow(projectName);
+ Log.debug("[{}] Got version ID for push: {}", projectName, versionID);
+ approveSnapshot(versionID, candidate);
+ Log.debug("[{}] Approved version ID: {}", projectName, versionID);
+ dbStore.setLastAccessedTime(projectName, Timestamp.valueOf(LocalDateTime.now()));
+ } else {
+ Log.warn("[{}] Went out of date while waiting for push", projectName);
+ throw new OutOfDateException();
+ }
}
+ }
- /**
- * Does the work of pushing to a project, assuming the project lock is held.
- * The {@link WriteLatexPutHook} is the original caller, and when we return
- * without throwing, the commit is committed.
- *
- * We start off by creating a postback key, which is given in the url when
- * the Overleaf app tries to access the atts.
- *
- * Then creates a {@link CandidateSnapshot} from the old and new project
- * contents. The
- * {@link CandidateSnapshot} is created using
- * {@link #createCandidateSnapshot(String, RawDirectory, RawDirectory)},
- * which creates the snapshot object and writes the push files to the
- * atts directory, which is served by the {@link PostbackHandler}.
- * The files are deleted at the end of a try-with-resources block.
- *
- * Then 3 things are used to make the push request to the snapshot API:
- * 1. The oauth2
- * 2. The candidate snapshot
- * 3. The postback key
- *
- * If the snapshot API reports this as not successful, we immediately throw
- * an {@link OutOfDateException}, which goes back to the user.
- *
- * Otherwise, we wait (with a timeout) on a promise from the postback
- * manager, which can throw back to the user.
- *
- * If this is successful, we approve the snapshot with
- * {@link #approveSnapshot(int, CandidateSnapshot)}, which updates our side
- * of the push: the latest version and the URL index store.
- *
- * Then, we set the last accessed time for the swap store.
- *
- * Finally, after we return, the push to the repo from the hook is
- * successful and the repo gets updated.
- *
- * @param oauth2
- * @param projectName
- * @param directoryContents
- * @param oldDirectoryContents
- * @throws IOException
- * @throws MissingRepositoryException
- * @throws ForbiddenException
- * @throws SnapshotPostException
- * @throws GitUserException
- */
- private void pushCritical(
- Optional oauth2,
- String projectName,
- RawDirectory directoryContents,
- RawDirectory oldDirectoryContents
- ) throws IOException, MissingRepositoryException, ForbiddenException, SnapshotPostException, GitUserException {
- Optional maxFileNum = config
- .getRepoStore()
- .flatMap(RepoStoreConfig::getMaxFileNum);
- if (maxFileNum.isPresent()) {
- long maxFileNum_ = maxFileNum.get();
- if (directoryContents.getFileTable().size() > maxFileNum_) {
- Log.warn("[{}] Too many files: {}/{}", projectName, directoryContents.getFileTable().size(), maxFileNum_);
- throw new FileLimitExceededException(directoryContents.getFileTable().size(), maxFileNum_);
+ /*
+ * A public call that should originate from the {@link FileHandler}.
+ *
+ * The {@link FileHandler} serves atts to the Overleaf app during a push.
+ * The Overleaf app includes the postback key in the request, which was
+ * originally given on a push request.
+ *
+ * This method checks that the postback key matches, and throws if not.
+ *
+ * The FileHandler should not serve the file if this throws.
+ * @param projectName The project name that this key belongs to
+ * @param postbackKey The key
+ * @throws InvalidPostbackKeyException If the key doesn't match
+ */
+ public void checkPostbackKey(String projectName, String postbackKey)
+ throws InvalidPostbackKeyException {
+ postbackManager.checkPostbackKey(projectName, postbackKey);
+ }
+
+ /*
+ * A public call that originates from the postback thread
+ * {@link PostbackContents#processPostback()}, i.e. once the Overleaf app
+ * has fetched all the atts and has committed the push and is happy, it
+ * calls back here, fulfilling the promise that the push
+ * {@link #push(Optional, String, RawDirectory, RawDirectory, String)}
+ * is waiting on.
+ *
+ * The Overleaf app will have invented a new version for the push, which is
+ * passed to the promise for the original push request to update the app.
+ * @param projectName The name of the project being pushed to
+ * @param postbackKey The postback key being used
+ * @param versionID the new version id to use
+ * @throws UnexpectedPostbackException if the postback key is invalid
+ */
+ public void postbackReceivedSuccessfully(String projectName, String postbackKey, int versionID)
+ throws UnexpectedPostbackException {
+ Log.debug(
+ "[{}]" + " Postback received by postback thread, version: {}", projectName, versionID);
+ postbackManager.postVersionIDForProject(projectName, versionID, postbackKey);
+ }
+
+ /*
+ * As with {@link #postbackReceivedSuccessfully(String, String, int)},
+ * but with an exception instead.
+ *
+ * This is based on the JSON body of the postback from the Overleaf app.
+ *
+ * The most likely problem is an {@link OutOfDateException}.
+ * @param projectName The name of the project
+ * @param postbackKey The postback key being used
+ * @param exception The exception encountered
+ * @throws UnexpectedPostbackException If the postback key is invalid
+ */
+ public void postbackReceivedWithException(
+ String projectName, String postbackKey, SnapshotPostException exception)
+ throws UnexpectedPostbackException {
+ Log.warn("[{}] Postback received with exception", projectName);
+ postbackManager.postExceptionForProject(projectName, exception, postbackKey);
+ }
+
+ /*
+ * Delete a project's data
+ */
+ public void deleteProject(String projectName) {
+ Log.info("[{}] deleting project", projectName);
+ dbStore.deleteProject(projectName);
+ try {
+ repoStore.remove(projectName);
+ } catch (IOException e) {
+ Log.warn("Failed to delete repository for project {}: {}", projectName, e);
+ }
+ swapStore.remove(projectName);
+ }
+
+ /* PRIVATE */
+
+ /*
+ * Called by {@link #getUpdatedRepoCritical(Optional, String)}
+ *
+ * Does the actual work of getting the snapshots for a project from the
+ * snapshot API and committing them to a repo.
+ *
+ * If any snapshots were found, sets the latest version for the project.
+ *
+ * @param oauth2
+ * @param repo
+ * @throws IOException
+ * @throws GitUserException
+ */
+ private void updateProject(Optional oauth2, ProjectRepo repo)
+ throws IOException, GitUserException {
+ String projectName = repo.getProjectName();
+ int latestVersionId = dbStore.getLatestVersionForProject(projectName);
+ Deque snapshots = snapshotAPI.getSnapshots(oauth2, projectName, latestVersionId);
+
+ makeCommitsFromSnapshots(repo, snapshots);
+
+ // TODO: in case crashes around here, add an
+ // "updating_from_commit" column to the DB as a way to rollback the
+ // any failed partial updates before re-trying
+ // Also need to consider the empty state (a new git init'd repo being
+ // the rollback target)
+ if (!snapshots.isEmpty()) {
+ dbStore.setLatestVersionForProject(projectName, snapshots.getLast().getVersionID());
+ }
+ }
+
+ /*
+ * Called by {@link #updateProject(Optional, ProjectRepo)}.
+ *
+ * Performs the actual Git commits on the disk.
+ *
+ * Each commit adds files to the db store
+ * ({@link ResourceCache#get(String, String, String, Map, Map, Optional)},
+ * and then removes any files that were deleted.
+ * @param repo The repository to commit to
+ * @param snapshots The snapshots to commit
+ * @throws IOException If an IOException occurred
+ * @throws SizeLimitExceededException If one of the files was too big.
+ */
+ private void makeCommitsFromSnapshots(ProjectRepo repo, Collection snapshots)
+ throws IOException, GitUserException {
+ String name = repo.getProjectName();
+ Optional maxSize = config.getRepoStore().flatMap(RepoStoreConfig::getMaxFileSize);
+ for (Snapshot snapshot : snapshots) {
+ RawDirectory directory = repo.getDirectory();
+ Map fileTable = directory.getFileTable();
+ List files = new ArrayList<>();
+ files.addAll(snapshot.getSrcs());
+ for (RawFile file : files) {
+ long size = file.size();
+ /* Can't throw in ifPresent... */
+ if (maxSize.isPresent()) {
+ long maxSize_ = maxSize.get();
+ if (size >= maxSize_) {
+ throw new SizeLimitExceededException(Optional.of(file.getPath()), size, maxSize_);
}
}
- Log.debug("[{}] Pushing files ({} new, {} old)", projectName, directoryContents.getFileTable().size(), oldDirectoryContents.getFileTable().size());
- String postbackKey = postbackManager.makeKeyForProject(projectName);
- Log.debug(
- "[{}] Created postback key: {}",
- projectName,
- postbackKey
- );
- try (
- CandidateSnapshot candidate = createCandidateSnapshot(
- projectName,
- directoryContents,
- oldDirectoryContents
- );
- ) {
- Log.debug(
- "[{}] Candidate snapshot created: {}",
- projectName,
- candidate
- );
- PushResult result
- = snapshotAPI.push(oauth2, candidate, postbackKey);
- if (result.wasSuccessful()) {
- Log.debug(
- "[{}] Push to Overleaf successful",
- projectName
- );
- Log.debug("[{}] Waiting for postback...", projectName);
- int versionID =
- postbackManager.waitForVersionIdOrThrow(projectName);
- Log.debug(
- "[{}] Got version ID for push: {}",
- projectName,
- versionID
- );
- approveSnapshot(versionID, candidate);
- Log.debug(
- "[{}] Approved version ID: {}",
- projectName,
- versionID
- );
- dbStore.setLastAccessedTime(
- projectName,
- Timestamp.valueOf(LocalDateTime.now())
- );
- } else {
- Log.warn(
- "[{}] Went out of date while waiting for push",
- projectName
- );
- throw new OutOfDateException();
- }
- }
- }
-
- /**
- * A public call that should originate from the {@link FileHandler}.
- *
- * The {@link FileHandler} serves atts to the Overleaf app during a push.
- * The Overleaf app includes the postback key in the request, which was
- * originally given on a push request.
- *
- * This method checks that the postback key matches, and throws if not.
- *
- * The FileHandler should not serve the file if this throws.
- * @param projectName The project name that this key belongs to
- * @param postbackKey The key
- * @throws InvalidPostbackKeyException If the key doesn't match
- */
- public void checkPostbackKey(String projectName, String postbackKey)
- throws InvalidPostbackKeyException {
- postbackManager.checkPostbackKey(projectName, postbackKey);
- }
-
- /**
- * A public call that originates from the postback thread
- * {@link PostbackContents#processPostback()}, i.e. once the Overleaf app
- * has fetched all the atts and has committed the push and is happy, it
- * calls back here, fulfilling the promise that the push
- * {@link #push(Optional, String, RawDirectory, RawDirectory, String)}
- * is waiting on.
- *
- * The Overleaf app will have invented a new version for the push, which is
- * passed to the promise for the original push request to update the app.
- * @param projectName The name of the project being pushed to
- * @param postbackKey The postback key being used
- * @param versionID the new version id to use
- * @throws UnexpectedPostbackException if the postback key is invalid
- */
- public void postbackReceivedSuccessfully(
- String projectName,
- String postbackKey,
- int versionID
- ) throws UnexpectedPostbackException {
- Log.debug(
- "[{}]" +
- " Postback received by postback thread, version: {}",
- projectName,
- versionID);
- postbackManager.postVersionIDForProject(
- projectName,
- versionID,
- postbackKey
- );
- }
-
- /**
- * As with {@link #postbackReceivedSuccessfully(String, String, int)},
- * but with an exception instead.
- *
- * This is based on the JSON body of the postback from the Overleaf app.
- *
- * The most likely problem is an {@link OutOfDateException}.
- * @param projectName The name of the project
- * @param postbackKey The postback key being used
- * @param exception The exception encountered
- * @throws UnexpectedPostbackException If the postback key is invalid
- */
- public void postbackReceivedWithException(
- String projectName,
- String postbackKey,
- SnapshotPostException exception
- ) throws UnexpectedPostbackException {
- Log.warn("[{}] Postback received with exception", projectName);
- postbackManager.postExceptionForProject(
- projectName,
- exception,
- postbackKey
- );
- }
-
- /**
- * Delete a project's data
- */
- public void deleteProject(String projectName) {
- Log.info("[{}] deleting project", projectName);
- dbStore.deleteProject(projectName);
- try {
- repoStore.remove(projectName);
- } catch (IOException e) {
- Log.warn("Failed to delete repository for project {}: {}", projectName, e);
}
- swapStore.remove(projectName);
+ Map fetchedUrls = new HashMap<>();
+ for (SnapshotAttachment snapshotAttachment : snapshot.getAtts()) {
+ files.add(
+ resourceCache.get(
+ name,
+ snapshotAttachment.getUrl(),
+ snapshotAttachment.getPath(),
+ fileTable,
+ fetchedUrls,
+ maxSize));
+ }
+ Log.debug("[{}] Committing version ID: {}", name, snapshot.getVersionID());
+ Collection missingFiles =
+ repo.commitAndGetMissing(
+ new GitDirectoryContents(files, repoStore.getRootDirectory(), name, snapshot));
+ dbStore.deleteFilesForProject(name, missingFiles.toArray(new String[missingFiles.size()]));
}
+ }
- /* PRIVATE */
-
- /**
- * Called by {@link #getUpdatedRepoCritical(Optional, String)}
- *
- * Does the actual work of getting the snapshots for a project from the
- * snapshot API and committing them to a repo.
- *
- * If any snapshots were found, sets the latest version for the project.
- *
- * @param oauth2
- * @param repo
- * @throws IOException
- * @throws GitUserException
- */
- private void updateProject(
- Optional oauth2,
- ProjectRepo repo
- ) throws IOException, GitUserException {
- String projectName = repo.getProjectName();
- int latestVersionId = dbStore.getLatestVersionForProject(projectName);
- Deque snapshots = snapshotAPI.getSnapshots(
- oauth2, projectName, latestVersionId);
-
- makeCommitsFromSnapshots(repo, snapshots);
-
- // TODO: in case crashes around here, add an
- // "updating_from_commit" column to the DB as a way to rollback the
- // any failed partial updates before re-trying
- // Also need to consider the empty state (a new git init'd repo being
- // the rollback target)
- if (!snapshots.isEmpty()) {
- dbStore.setLatestVersionForProject(
- projectName,
- snapshots.getLast().getVersionID()
- );
- }
- }
-
- /**
- * Called by {@link #updateProject(Optional, ProjectRepo)}.
- *
- * Performs the actual Git commits on the disk.
- *
- * Each commit adds files to the db store
- * ({@link ResourceCache#get(String, String, String, Map, Map, Optional)},
- * and then removes any files that were deleted.
- * @param repo The repository to commit to
- * @param snapshots The snapshots to commit
- * @throws IOException If an IOException occurred
- * @throws SizeLimitExceededException If one of the files was too big.
- */
- private void makeCommitsFromSnapshots(
- ProjectRepo repo,
- Collection snapshots
- ) throws IOException, GitUserException {
- String name = repo.getProjectName();
- Optional maxSize = config
- .getRepoStore()
- .flatMap(RepoStoreConfig::getMaxFileSize);
- for (Snapshot snapshot : snapshots) {
- RawDirectory directory = repo.getDirectory();
- Map fileTable = directory.getFileTable();
- List files = new ArrayList<>();
- files.addAll(snapshot.getSrcs());
- for (RawFile file : files) {
- long size = file.size();
- /* Can't throw in ifPresent... */
- if (maxSize.isPresent()) {
- long maxSize_ = maxSize.get();
- if (size >= maxSize_) {
- throw new SizeLimitExceededException(
- Optional.of(file.getPath()), size, maxSize_);
- }
- }
- }
- Map fetchedUrls = new HashMap<>();
- for (SnapshotAttachment snapshotAttachment : snapshot.getAtts()) {
- files.add(
- resourceCache.get(
- name,
- snapshotAttachment.getUrl(),
- snapshotAttachment.getPath(),
- fileTable,
- fetchedUrls,
- maxSize
- )
- );
- }
- Log.debug(
- "[{}] Committing version ID: {}",
- name,
- snapshot.getVersionID()
- );
- Collection missingFiles = repo.commitAndGetMissing(
- new GitDirectoryContents(
- files,
- repoStore.getRootDirectory(),
- name,
- snapshot
- )
- );
- dbStore.deleteFilesForProject(
- name,
- missingFiles.toArray(new String[missingFiles.size()])
- );
- }
- }
-
- /**
- * Called by
- * {@link #pushCritical(Optional, String, RawDirectory, RawDirectory)}.
- *
- * This call consists of 2 things: Creating the candidate snapshot,
- * and writing the atts to the atts directory.
- *
- * The candidate snapshot RAIIs away those atts (use try-with-resources).
- * @param projectName The name of the project
- * @param directoryContents The new directory contents
- * @param oldDirectoryContents The old directory contents
- * @return The {@link CandidateSnapshot} created
- * @throws IOException If an I/O exception occurred on writing
- */
- private CandidateSnapshot createCandidateSnapshot(
- String projectName,
- RawDirectory directoryContents,
- RawDirectory oldDirectoryContents
- ) throws IOException {
- CandidateSnapshot candidateSnapshot = new CandidateSnapshot(
- projectName,
- dbStore.getLatestVersionForProject(projectName),
- directoryContents,
- oldDirectoryContents
- );
- candidateSnapshot.writeServletFiles(repoStore.getRootDirectory());
- return candidateSnapshot;
- }
-
- /**
- * Called by
- * {@link #pushCritical(Optional, String, RawDirectory, RawDirectory)}.
- *
- * This method approves a push by setting the latest version and removing
- * any deleted files from the db store (files were already added by the
- * resources cache).
- * @param versionID
- * @param candidateSnapshot
- */
- private void approveSnapshot(
- int versionID,
- CandidateSnapshot candidateSnapshot
- ) {
- List deleted = candidateSnapshot.getDeleted();
- dbStore.setLatestVersionForProject(
- candidateSnapshot.getProjectName(),
- versionID
- );
- dbStore.deleteFilesForProject(
- candidateSnapshot.getProjectName(),
- deleted.toArray(new String[deleted.size()])
- );
- }
+ /*
+ * Called by
+ * {@link #pushCritical(Optional, String, RawDirectory, RawDirectory)}.
+ *
+ * This call consists of 2 things: Creating the candidate snapshot,
+ * and writing the atts to the atts directory.
+ *
+ * The candidate snapshot RAIIs away those atts (use try-with-resources).
+ * @param projectName The name of the project
+ * @param directoryContents The new directory contents
+ * @param oldDirectoryContents The old directory contents
+ * @return The {@link CandidateSnapshot} created
+ * @throws IOException If an I/O exception occurred on writing
+ */
+ private CandidateSnapshot createCandidateSnapshot(
+ String projectName, RawDirectory directoryContents, RawDirectory oldDirectoryContents)
+ throws IOException {
+ CandidateSnapshot candidateSnapshot =
+ new CandidateSnapshot(
+ projectName,
+ dbStore.getLatestVersionForProject(projectName),
+ directoryContents,
+ oldDirectoryContents);
+ candidateSnapshot.writeServletFiles(repoStore.getRootDirectory());
+ return candidateSnapshot;
+ }
+ /*
+ * Called by
+ * {@link #pushCritical(Optional, String, RawDirectory, RawDirectory)}.
+ *
+ * This method approves a push by setting the latest version and removing
+ * any deleted files from the db store (files were already added by the
+ * resources cache).
+ * @param versionID
+ * @param candidateSnapshot
+ */
+ private void approveSnapshot(int versionID, CandidateSnapshot candidateSnapshot) {
+ List deleted = candidateSnapshot.getDeleted();
+ dbStore.setLatestVersionForProject(candidateSnapshot.getProjectName(), versionID);
+ dbStore.deleteFilesForProject(
+ candidateSnapshot.getProjectName(), deleted.toArray(new String[deleted.size()]));
+ }
}
diff --git a/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/db/DBInitException.java b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/db/DBInitException.java
index 0c8a6d7b04..633ae5195e 100644
--- a/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/db/DBInitException.java
+++ b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/db/DBInitException.java
@@ -1,20 +1,19 @@
package uk.ac.ic.wlgitbridge.bridge.db;
-/**
+/*
* Created by winston on 23/08/2016.
*/
public class DBInitException extends RuntimeException {
- public DBInitException(String message) {
- super(message);
- }
+ public DBInitException(String message) {
+ super(message);
+ }
- public DBInitException(String message, Throwable cause) {
- super(message, cause);
- }
-
- public DBInitException(Throwable cause) {
- super(cause);
- }
+ public DBInitException(String message, Throwable cause) {
+ super(message, cause);
+ }
+ public DBInitException(Throwable cause) {
+ super(cause);
+ }
}
diff --git a/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/db/DBStore.java b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/db/DBStore.java
index 9b7f8eebd6..01f37773ca 100644
--- a/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/db/DBStore.java
+++ b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/db/DBStore.java
@@ -3,46 +3,46 @@ package uk.ac.ic.wlgitbridge.bridge.db;
import java.sql.Timestamp;
import java.util.List;
-/**
+/*
* Created by winston on 20/08/2016.
*/
public interface DBStore {
- int getNumProjects();
+ int getNumProjects();
- List getProjectNames();
+ List getProjectNames();
- void setLatestVersionForProject(String project, int versionID);
+ void setLatestVersionForProject(String project, int versionID);
- int getLatestVersionForProject(String project);
+ int getLatestVersionForProject(String project);
- void addURLIndexForProject(String projectName, String url, String path);
+ void addURLIndexForProject(String projectName, String url, String path);
- void deleteFilesForProject(String project, String... files);
+ void deleteFilesForProject(String project, String... files);
- String getPathForURLInProject(String projectName, String url);
+ String getPathForURLInProject(String projectName, String url);
- String getOldestUnswappedProject();
+ String getOldestUnswappedProject();
- void swap(String projectName, String compressionMethod);
+ void swap(String projectName, String compressionMethod);
- void restore(String projectName);
+ void restore(String projectName);
- String getSwapCompression(String projectName);
+ String getSwapCompression(String projectName);
- int getNumUnswappedProjects();
+ int getNumUnswappedProjects();
- ProjectState getProjectState(String projectName);
+ ProjectState getProjectState(String projectName);
- /**
- * Sets the last accessed time for the given project name.
- * @param projectName the project's name
- * @param time the time, or null if the project is to be swapped
- */
- void setLastAccessedTime(String projectName, Timestamp time);
+ /*
+ * Sets the last accessed time for the given project name.
+ * @param projectName the project's name
+ * @param time the time, or null if the project is to be swapped
+ */
+ void setLastAccessedTime(String projectName, Timestamp time);
- /**
- * Delete the metadata associated with the given project.
- */
- void deleteProject(String projectName);
+ /*
+ * Delete the metadata associated with the given project.
+ */
+ void deleteProject(String projectName);
}
diff --git a/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/db/ProjectState.java b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/db/ProjectState.java
index ad389f5ac1..3e85116cee 100644
--- a/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/db/ProjectState.java
+++ b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/db/ProjectState.java
@@ -1,12 +1,10 @@
package uk.ac.ic.wlgitbridge.bridge.db;
-/**
+/*
* Created by winston on 24/08/2016.
*/
public enum ProjectState {
-
- NOT_PRESENT,
- PRESENT,
- SWAPPED
-
+ NOT_PRESENT,
+ PRESENT,
+ SWAPPED
}
diff --git a/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/db/noop/NoopDbStore.java b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/db/noop/NoopDbStore.java
index 15846f28a4..20d42022a2 100644
--- a/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/db/noop/NoopDbStore.java
+++ b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/db/noop/NoopDbStore.java
@@ -1,78 +1,70 @@
package uk.ac.ic.wlgitbridge.bridge.db.noop;
-import uk.ac.ic.wlgitbridge.bridge.db.DBStore;
-import uk.ac.ic.wlgitbridge.bridge.db.ProjectState;
-
import java.sql.Timestamp;
import java.util.List;
+import uk.ac.ic.wlgitbridge.bridge.db.DBStore;
+import uk.ac.ic.wlgitbridge.bridge.db.ProjectState;
public class NoopDbStore implements DBStore {
- @Override
- public int getNumProjects() {
- return 0;
- }
+ @Override
+ public int getNumProjects() {
+ return 0;
+ }
- @Override
- public List getProjectNames() {
- return null;
- }
+ @Override
+ public List getProjectNames() {
+ return null;
+ }
- @Override
- public void setLatestVersionForProject(String project, int versionID) {
+ @Override
+ public void setLatestVersionForProject(String project, int versionID) {}
- }
+ @Override
+ public int getLatestVersionForProject(String project) {
+ return 0;
+ }
- @Override
- public int getLatestVersionForProject(String project) {
- return 0;
- }
+ @Override
+ public void addURLIndexForProject(String projectName, String url, String path) {}
- @Override
- public void addURLIndexForProject(String projectName, String url, String path) {
+ @Override
+ public void deleteFilesForProject(String project, String... files) {}
- }
+ @Override
+ public String getPathForURLInProject(String projectName, String url) {
+ return null;
+ }
- @Override
- public void deleteFilesForProject(String project, String... files) {
+ @Override
+ public String getOldestUnswappedProject() {
+ return null;
+ }
- }
+ @Override
+ public int getNumUnswappedProjects() {
+ return 0;
+ }
- @Override
- public String getPathForURLInProject(String projectName, String url) {
- return null;
- }
+ @Override
+ public ProjectState getProjectState(String projectName) {
+ return null;
+ }
- @Override
- public String getOldestUnswappedProject() {
- return null;
- }
+ @Override
+ public void setLastAccessedTime(String projectName, Timestamp time) {}
- @Override
- public int getNumUnswappedProjects() {
- return 0;
- }
+ @Override
+ public void swap(String projectName, String compressionMethod) {}
- @Override
- public ProjectState getProjectState(String projectName) {
- return null;
- }
+ @Override
+ public void restore(String projectName) {}
- @Override
- public void setLastAccessedTime(String projectName, Timestamp time) {
- }
+ @Override
+ public String getSwapCompression(String projectName) {
+ return null;
+ }
- @Override
- public void swap(String projectName, String compressionMethod) {}
-
- @Override
- public void restore(String projectName) {}
-
- @Override
- public String getSwapCompression(String projectName) {
- return null;
- }
-
- @Override
- public void deleteProject(String projectName) {}
+ @Override
+ public void deleteProject(String projectName) {}
}
diff --git a/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/db/sqlite/SQLQuery.java b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/db/sqlite/SQLQuery.java
index 0873d133b8..faa6a3ff11 100644
--- a/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/db/sqlite/SQLQuery.java
+++ b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/db/sqlite/SQLQuery.java
@@ -3,11 +3,10 @@ package uk.ac.ic.wlgitbridge.bridge.db.sqlite;
import java.sql.ResultSet;
import java.sql.SQLException;
-/**
+/*
* Created by Winston on 20/11/14.
*/
public interface SQLQuery extends SQLUpdate {
- public T processResultSet(ResultSet resultSet) throws SQLException;
-
+ public T processResultSet(ResultSet resultSet) throws SQLException;
}
diff --git a/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/db/sqlite/SQLUpdate.java b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/db/sqlite/SQLUpdate.java
index 167be212c0..9e79fdcfc8 100644
--- a/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/db/sqlite/SQLUpdate.java
+++ b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/db/sqlite/SQLUpdate.java
@@ -3,16 +3,12 @@ package uk.ac.ic.wlgitbridge.bridge.db.sqlite;
import java.sql.PreparedStatement;
import java.sql.SQLException;
-/**
+/*
* Created by Winston on 20/11/14.
*/
public interface SQLUpdate {
- String getSQL();
- default void addParametersToStatement(
- PreparedStatement statement
- ) throws SQLException {
-
- }
+ String getSQL();
+ default void addParametersToStatement(PreparedStatement statement) throws SQLException {}
}
diff --git a/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/db/sqlite/SqliteDBStore.java b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/db/sqlite/SqliteDBStore.java
index 1699915da9..6647a5984b 100644
--- a/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/db/sqlite/SqliteDBStore.java
+++ b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/db/sqlite/SqliteDBStore.java
@@ -1,6 +1,10 @@
package uk.ac.ic.wlgitbridge.bridge.db.sqlite;
import com.google.common.base.Preconditions;
+import java.io.File;
+import java.sql.*;
+import java.util.List;
+import java.util.stream.Stream;
import uk.ac.ic.wlgitbridge.bridge.db.DBInitException;
import uk.ac.ic.wlgitbridge.bridge.db.DBStore;
import uk.ac.ic.wlgitbridge.bridge.db.ProjectState;
@@ -10,225 +14,214 @@ import uk.ac.ic.wlgitbridge.bridge.db.sqlite.update.create.*;
import uk.ac.ic.wlgitbridge.bridge.db.sqlite.update.delete.*;
import uk.ac.ic.wlgitbridge.bridge.db.sqlite.update.insert.*;
-import java.io.File;
-import java.sql.*;
-import java.util.List;
-import java.util.stream.Stream;
-
-/**
+/*
* Created by Winston on 17/11/14.
*/
public class SqliteDBStore implements DBStore {
- private final Connection connection;
- private int heapLimitBytes = 0;
+ private final Connection connection;
+ private int heapLimitBytes = 0;
- public SqliteDBStore(File dbFile) {
- this(dbFile, 0);
+ public SqliteDBStore(File dbFile) {
+ this(dbFile, 0);
+ }
+
+ public SqliteDBStore(File dbFile, int heapLimitBytes) {
+ this.heapLimitBytes = heapLimitBytes;
+ try {
+ connection = openConnectionTo(dbFile);
+ createTables();
+ } catch (Throwable t) {
+ throw new DBInitException(t);
+ }
+ }
+
+ @Override
+ public int getNumProjects() {
+ return query(new GetNumProjects());
+ }
+
+ @Override
+ public List getProjectNames() {
+ return query(new GetProjectNamesSQLQuery());
+ }
+
+ @Override
+ public void setLatestVersionForProject(String projectName, int versionID) {
+ update(new SetProjectSQLUpdate(projectName, versionID));
+ }
+
+ @Override
+ public int getLatestVersionForProject(String projectName) {
+ return query(new GetLatestVersionForProjectSQLQuery(projectName));
+ }
+
+ @Override
+ public void addURLIndexForProject(String projectName, String url, String path) {
+ update(new AddURLIndexSQLUpdate(projectName, url, path));
+ }
+
+ @Override
+ public void deleteFilesForProject(String projectName, String... paths) {
+ update(new DeleteFilesForProjectSQLUpdate(projectName, paths));
+ }
+
+ @Override
+ public String getPathForURLInProject(String projectName, String url) {
+ return query(new GetPathForURLInProjectSQLQuery(projectName, url));
+ }
+
+ @Override
+ public String getOldestUnswappedProject() {
+ return query(new GetOldestProjectName());
+ }
+
+ @Override
+ public int getNumUnswappedProjects() {
+ return query(new GetNumUnswappedProjects());
+ }
+
+ @Override
+ public ProjectState getProjectState(String projectName) {
+ return query(new GetProjectState(projectName));
+ }
+
+ @Override
+ public void setLastAccessedTime(String projectName, Timestamp lastAccessed) {
+ update(new SetProjectLastAccessedTime(projectName, lastAccessed));
+ }
+
+ @Override
+ public void swap(String projectName, String compressionMethod) {
+ update(new UpdateSwap(projectName, compressionMethod));
+ }
+
+ @Override
+ public void restore(String projectName) {
+ update(new UpdateRestore(projectName));
+ }
+
+ @Override
+ public String getSwapCompression(String projectName) {
+ return query(new GetSwapCompression(projectName));
+ }
+
+ @Override
+ public void deleteProject(String projectName) {
+ update(new DeleteAllFilesInProjectSQLUpdate(projectName));
+ update(new DeleteProjectSQLUpdate(projectName));
+ }
+
+ private Connection openConnectionTo(File dbFile) {
+ File parentDir = dbFile.getParentFile();
+ if (!parentDir.exists() && !parentDir.mkdirs()) {
+ throw new DBInitException(
+ parentDir.getAbsolutePath()
+ + " directory didn't exist, "
+ + "and unable to create. Check your permissions.");
+ }
+ try {
+ Class.forName("org.sqlite.JDBC");
+ } catch (ClassNotFoundException e) {
+ throw new DBInitException(e);
+ }
+ try {
+ return DriverManager.getConnection("jdbc:sqlite:" + dbFile.getAbsolutePath());
+ } catch (SQLException e) {
+ throw new DBInitException("Unable to connect to DB", e);
+ }
+ }
+
+ private void createTables() {
+ /* Migrations */
+ /* We need to eat exceptions from here */
+ try {
+ doUpdate(new SetSoftHeapLimitPragma(this.heapLimitBytes));
+ } catch (SQLException ignore) {
+ }
+ try {
+ doUpdate(new ProjectsAddLastAccessed());
+ } catch (SQLException ignore) {
+ }
+ try {
+ doUpdate(new ProjectsAddSwapTime());
+ } catch (SQLException ignore) {
+ }
+ try {
+ doUpdate(new ProjectsAddRestoreTime());
+ } catch (SQLException ignore) {
+ }
+ try {
+ doUpdate(new ProjectsAddSwapCompression());
+ } catch (SQLException ignore) {
}
- public SqliteDBStore(File dbFile, int heapLimitBytes) {
- this.heapLimitBytes = heapLimitBytes;
- try {
- connection = openConnectionTo(dbFile);
- createTables();
- } catch (Throwable t) {
- throw new DBInitException(t);
- }
+ /* Create tables (if they don't exist) */
+ Stream.of(
+ new CreateProjectsTableSQLUpdate(),
+ new CreateProjectsIndexLastAccessed(),
+ new CreateURLIndexStoreSQLUpdate(),
+ new CreateIndexURLIndexStore())
+ .forEach(this::update);
+
+ /* In the case of needing to change the schema, we need to check that
+ migrations didn't just fail */
+ Preconditions.checkState(query(new LastAccessedColumnExists()));
+ Preconditions.checkState(query(new SwapTimeColumnExists()));
+ Preconditions.checkState(query(new RestoreTimeColumnExists()));
+ Preconditions.checkState(query(new SwapCompressionColumnExists()));
+ }
+
+ private void update(SQLUpdate update) {
+ try {
+ doUpdate(update);
+ } catch (SQLException e) {
+ throw new RuntimeException(e);
}
+ }
- @Override
- public int getNumProjects() {
- return query(new GetNumProjects());
+ private T query(SQLQuery query) {
+ try {
+ return doQuery(query);
+ } catch (SQLException e) {
+ throw new RuntimeException(e);
}
+ }
- @Override
- public List getProjectNames() {
- return query(new GetProjectNamesSQLQuery());
+ private void doUpdate(SQLUpdate update) throws SQLException {
+ PreparedStatement statement = null;
+ try {
+ statement = connection.prepareStatement(update.getSQL());
+ update.addParametersToStatement(statement);
+ statement.executeUpdate();
+ } catch (SQLException e) {
+ throw e;
+ } finally {
+ try {
+ statement.close();
+ } catch (Throwable t) {
+ throw new SQLException(t);
+ }
}
+ }
- @Override
- public void setLatestVersionForProject(
- String projectName,
- int versionID
- ) {
- update(new SetProjectSQLUpdate(projectName, versionID));
+ private T doQuery(SQLQuery query) throws SQLException {
+ PreparedStatement statement = null;
+ ResultSet results = null;
+ try {
+ statement = connection.prepareStatement(query.getSQL());
+ query.addParametersToStatement(statement);
+ results = statement.executeQuery();
+ return query.processResultSet(results);
+ } catch (SQLException e) {
+ throw e;
+ } finally {
+ if (statement != null) {
+ statement.close();
+ }
+ if (results != null) {
+ results.close();
+ }
}
-
- @Override
- public int getLatestVersionForProject(
- String projectName
- ) {
- return query(new GetLatestVersionForProjectSQLQuery(projectName));
- }
-
- @Override
- public void addURLIndexForProject(
- String projectName,
- String url,
- String path
- ) {
- update(new AddURLIndexSQLUpdate(projectName, url, path));
- }
-
- @Override
- public void deleteFilesForProject(
- String projectName,
- String... paths
- ) {
- update(new DeleteFilesForProjectSQLUpdate(projectName, paths));
- }
-
- @Override
- public String getPathForURLInProject(
- String projectName,
- String url
- ) {
- return query(new GetPathForURLInProjectSQLQuery(projectName, url));
- }
-
- @Override
- public String getOldestUnswappedProject() {
- return query(new GetOldestProjectName());
- }
-
- @Override
- public int getNumUnswappedProjects() {
- return query(new GetNumUnswappedProjects());
- }
-
- @Override
- public ProjectState getProjectState(String projectName) {
- return query(new GetProjectState(projectName));
- }
-
- @Override
- public void setLastAccessedTime(
- String projectName,
- Timestamp lastAccessed
- ) {
- update(new SetProjectLastAccessedTime(projectName, lastAccessed));
- }
-
- @Override
- public void swap(String projectName, String compressionMethod) {
- update(new UpdateSwap(projectName, compressionMethod));
- }
-
- @Override
- public void restore(String projectName) {
- update(new UpdateRestore(projectName));
- }
-
- @Override
- public String getSwapCompression(String projectName) {
- return query(new GetSwapCompression(projectName));
- }
-
- @Override
- public void deleteProject(String projectName) {
- update(new DeleteAllFilesInProjectSQLUpdate(projectName));
- update(new DeleteProjectSQLUpdate(projectName));
- }
-
- private Connection openConnectionTo(File dbFile) {
- File parentDir = dbFile.getParentFile();
- if (!parentDir.exists() && !parentDir.mkdirs()) {
- throw new DBInitException(
- parentDir.getAbsolutePath() + " directory didn't exist, " +
- "and unable to create. Check your permissions."
- );
- }
- try {
- Class.forName("org.sqlite.JDBC");
- } catch (ClassNotFoundException e) {
- throw new DBInitException(e);
- }
- try {
- return DriverManager.getConnection(
- "jdbc:sqlite:" + dbFile.getAbsolutePath()
- );
- } catch (SQLException e) {
- throw new DBInitException("Unable to connect to DB", e);
- }
- }
-
- private void createTables() {
- /* Migrations */
- /* We need to eat exceptions from here */
- try { doUpdate(new SetSoftHeapLimitPragma(this.heapLimitBytes)); } catch (SQLException ignore) {}
- try { doUpdate(new ProjectsAddLastAccessed()); } catch (SQLException ignore) {}
- try { doUpdate(new ProjectsAddSwapTime()); } catch (SQLException ignore) {}
- try { doUpdate(new ProjectsAddRestoreTime()); } catch (SQLException ignore) {}
- try { doUpdate(new ProjectsAddSwapCompression()); } catch (SQLException ignore) {}
-
- /* Create tables (if they don't exist) */
- Stream.of(
- new CreateProjectsTableSQLUpdate(),
- new CreateProjectsIndexLastAccessed(),
- new CreateURLIndexStoreSQLUpdate(),
- new CreateIndexURLIndexStore()
- ).forEach(this::update);
-
- /* In the case of needing to change the schema, we need to check that
- migrations didn't just fail */
- Preconditions.checkState(query(new LastAccessedColumnExists()));
- Preconditions.checkState(query(new SwapTimeColumnExists()));
- Preconditions.checkState(query(new RestoreTimeColumnExists()));
- Preconditions.checkState(query(new SwapCompressionColumnExists()));
- }
-
- private void update(SQLUpdate update) {
- try {
- doUpdate(update);
- } catch (SQLException e) {
- throw new RuntimeException(e);
- }
- }
-
- private T query(SQLQuery query) {
- try {
- return doQuery(query);
- } catch (SQLException e) {
- throw new RuntimeException(e);
- }
- }
-
- private void doUpdate(SQLUpdate update) throws SQLException {
- PreparedStatement statement = null;
- try {
- statement = connection.prepareStatement(update.getSQL());
- update.addParametersToStatement(statement);
- statement.executeUpdate();
- } catch (SQLException e) {
- throw e;
- } finally {
- try {
- statement.close();
- } catch (Throwable t) {
- throw new SQLException(t);
- }
- }
- }
-
- private T doQuery(SQLQuery query) throws SQLException {
- PreparedStatement statement = null;
- ResultSet results = null;
- try {
- statement = connection.prepareStatement(query.getSQL());
- query.addParametersToStatement(statement);
- results = statement.executeQuery();
- return query.processResultSet(results);
- } catch (SQLException e) {
- throw e;
- } finally {
- if (statement != null) {
- statement.close();
- }
- if (results != null) {
- results.close();
- }
- }
- }
-
+ }
}
diff --git a/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/db/sqlite/query/GetLatestVersionForProjectSQLQuery.java b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/db/sqlite/query/GetLatestVersionForProjectSQLQuery.java
index 4633fcf7cc..cc74e771f1 100644
--- a/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/db/sqlite/query/GetLatestVersionForProjectSQLQuery.java
+++ b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/db/sqlite/query/GetLatestVersionForProjectSQLQuery.java
@@ -1,43 +1,40 @@
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 uk.ac.ic.wlgitbridge.bridge.db.sqlite.SQLQuery;
-/**
+/*
* Created by Winston on 20/11/14.
*/
public class GetLatestVersionForProjectSQLQuery implements SQLQuery {
- private static final String GET_VERSION_IDS_FOR_PROJECT_NAME =
- "SELECT `version_id` FROM `projects` WHERE `name` = ?";
+ private static final String GET_VERSION_IDS_FOR_PROJECT_NAME =
+ "SELECT `version_id` FROM `projects` WHERE `name` = ?";
- private final String projectName;
+ private final String projectName;
- public GetLatestVersionForProjectSQLQuery(String projectName) {
- this.projectName = projectName;
+ public GetLatestVersionForProjectSQLQuery(String projectName) {
+ this.projectName = projectName;
+ }
+
+ @Override
+ public Integer processResultSet(ResultSet resultSet) throws SQLException {
+ int versionID = 0;
+ while (resultSet.next()) {
+ versionID = resultSet.getInt("version_id");
}
+ return versionID;
+ }
- @Override
- public Integer processResultSet(ResultSet resultSet) throws SQLException {
- int versionID = 0;
- while (resultSet.next()) {
- versionID = resultSet.getInt("version_id");
- }
- return versionID;
- }
+ @Override
+ public String getSQL() {
+ return GET_VERSION_IDS_FOR_PROJECT_NAME;
+ }
- @Override
- public String getSQL() {
- return GET_VERSION_IDS_FOR_PROJECT_NAME;
- }
-
- @Override
- public void addParametersToStatement(
- PreparedStatement statement
- ) throws SQLException {
- statement.setString(1, projectName);
- }
+ @Override
+ public void addParametersToStatement(PreparedStatement statement) throws SQLException {
+ statement.setString(1, projectName);
+ }
}
diff --git a/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/db/sqlite/query/GetNumProjects.java b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/db/sqlite/query/GetNumProjects.java
index e5123c2ea1..30e00be5cb 100644
--- a/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/db/sqlite/query/GetNumProjects.java
+++ b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/db/sqlite/query/GetNumProjects.java
@@ -1,30 +1,26 @@
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;
+import uk.ac.ic.wlgitbridge.bridge.db.sqlite.SQLQuery;
-/**
+/*
* Created by winston on 24/08/2016.
*/
public class GetNumProjects implements SQLQuery {
- private static final String GET_NUM_PROJECTS =
- "SELECT COUNT(*)\n" +
- " FROM `projects`";
+ private static final String GET_NUM_PROJECTS = "SELECT COUNT(*)\n" + " FROM `projects`";
- @Override
- public String getSQL() {
- return GET_NUM_PROJECTS;
+ @Override
+ public String getSQL() {
+ return GET_NUM_PROJECTS;
+ }
+
+ @Override
+ public Integer processResultSet(ResultSet resultSet) throws SQLException {
+ while (resultSet.next()) {
+ return resultSet.getInt("COUNT(*)");
}
-
- @Override
- public Integer processResultSet(ResultSet resultSet) throws SQLException {
- while (resultSet.next()) {
- return resultSet.getInt("COUNT(*)");
- }
- throw new IllegalStateException("Count always returns results");
- }
-
+ throw new IllegalStateException("Count always returns results");
+ }
}
diff --git a/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/db/sqlite/query/GetNumUnswappedProjects.java b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/db/sqlite/query/GetNumUnswappedProjects.java
index ec7a89b980..512f15cc53 100644
--- a/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/db/sqlite/query/GetNumUnswappedProjects.java
+++ b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/db/sqlite/query/GetNumUnswappedProjects.java
@@ -1,31 +1,27 @@
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;
+import uk.ac.ic.wlgitbridge.bridge.db.sqlite.SQLQuery;
-/**
+/*
* Created by winston on 24/08/2016.
*/
public class GetNumUnswappedProjects implements SQLQuery {
- private static final String GET_NUM_UNSWAPPED_PROJECTS =
- "SELECT COUNT(*)\n" +
- " FROM `projects`\n" +
- " WHERE `last_accessed` IS NOT NULL";
+ private static final String GET_NUM_UNSWAPPED_PROJECTS =
+ "SELECT COUNT(*)\n" + " FROM `projects`\n" + " WHERE `last_accessed` IS NOT NULL";
- @Override
- public String getSQL() {
- return GET_NUM_UNSWAPPED_PROJECTS;
+ @Override
+ public String getSQL() {
+ return GET_NUM_UNSWAPPED_PROJECTS;
+ }
+
+ @Override
+ public Integer processResultSet(ResultSet resultSet) throws SQLException {
+ while (resultSet.next()) {
+ return resultSet.getInt("COUNT(*)");
}
-
- @Override
- public Integer processResultSet(ResultSet resultSet) throws SQLException {
- while (resultSet.next()) {
- return resultSet.getInt("COUNT(*)");
- }
- throw new IllegalStateException("Count always returns results");
- }
-
+ throw new IllegalStateException("Count always returns results");
+ }
}
diff --git a/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/db/sqlite/query/GetOldestProjectName.java b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/db/sqlite/query/GetOldestProjectName.java
index 1128a53c01..3518977365 100644
--- a/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/db/sqlite/query/GetOldestProjectName.java
+++ b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/db/sqlite/query/GetOldestProjectName.java
@@ -1,31 +1,29 @@
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;
+import uk.ac.ic.wlgitbridge.bridge.db.sqlite.SQLQuery;
-/**
+/*
* Created by winston on 23/08/2016.
*/
public class GetOldestProjectName implements SQLQuery {
- private static final String GET_OLDEST_PROJECT_NAME =
- "SELECT `name`, MIN(`last_accessed`)\n" +
- " FROM `projects` \n" +
- " WHERE `last_accessed` IS NOT NULL;";
+ private static final String GET_OLDEST_PROJECT_NAME =
+ "SELECT `name`, MIN(`last_accessed`)\n"
+ + " FROM `projects` \n"
+ + " WHERE `last_accessed` IS NOT NULL;";
- @Override
- public String getSQL() {
- return GET_OLDEST_PROJECT_NAME;
+ @Override
+ public String getSQL() {
+ return GET_OLDEST_PROJECT_NAME;
+ }
+
+ @Override
+ public String processResultSet(ResultSet resultSet) throws SQLException {
+ while (resultSet.next()) {
+ return resultSet.getString("name");
}
-
- @Override
- public String processResultSet(ResultSet resultSet) throws SQLException {
- while (resultSet.next()) {
- return resultSet.getString("name");
- }
- return null;
- }
-
+ return null;
+ }
}
diff --git a/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/db/sqlite/query/GetPathForURLInProjectSQLQuery.java b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/db/sqlite/query/GetPathForURLInProjectSQLQuery.java
index b4905c7a8e..25beb18ad0 100644
--- a/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/db/sqlite/query/GetPathForURLInProjectSQLQuery.java
+++ b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/db/sqlite/query/GetPathForURLInProjectSQLQuery.java
@@ -1,50 +1,43 @@
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 uk.ac.ic.wlgitbridge.bridge.db.sqlite.SQLQuery;
-/**
+/*
* Created by Winston on 20/11/14.
*/
public class GetPathForURLInProjectSQLQuery implements SQLQuery {
- private static final String GET_URL_INDEXES_FOR_PROJECT_NAME =
- "SELECT `path` "
- + "FROM `url_index_store` "
- + "WHERE `project_name` = ? "
- + "AND `url` = ?";
+ private static final String GET_URL_INDEXES_FOR_PROJECT_NAME =
+ "SELECT `path` " + "FROM `url_index_store` " + "WHERE `project_name` = ? " + "AND `url` = ?";
- private final String projectName;
- private final String url;
+ private final String projectName;
+ private final String url;
- public GetPathForURLInProjectSQLQuery(String projectName, String url) {
- this.projectName = projectName;
- this.url = url;
+ public GetPathForURLInProjectSQLQuery(String projectName, String url) {
+ this.projectName = projectName;
+ this.url = url;
+ }
+
+ @Override
+ public String processResultSet(ResultSet resultSet) throws SQLException {
+ String path = null;
+ while (resultSet.next()) {
+ path = resultSet.getString("path");
}
+ return path;
+ }
- @Override
- public String processResultSet(ResultSet resultSet) throws SQLException {
- String path = null;
- while (resultSet.next()) {
- path = resultSet.getString("path");
- }
- return path;
- }
-
- @Override
- public String getSQL() {
- return GET_URL_INDEXES_FOR_PROJECT_NAME;
- }
-
- @Override
- public void addParametersToStatement(
- PreparedStatement statement
- ) throws SQLException {
- statement.setString(1, projectName);
- statement.setString(2, url);
- }
+ @Override
+ public String getSQL() {
+ return GET_URL_INDEXES_FOR_PROJECT_NAME;
+ }
+ @Override
+ public void addParametersToStatement(PreparedStatement statement) throws SQLException {
+ statement.setString(1, projectName);
+ statement.setString(2, url);
+ }
}
diff --git a/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/db/sqlite/query/GetProjectNamesSQLQuery.java b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/db/sqlite/query/GetProjectNamesSQLQuery.java
index fcf0f761b9..d56ad5c70e 100644
--- a/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/db/sqlite/query/GetProjectNamesSQLQuery.java
+++ b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/db/sqlite/query/GetProjectNamesSQLQuery.java
@@ -1,34 +1,29 @@
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;
import java.util.ArrayList;
import java.util.List;
+import uk.ac.ic.wlgitbridge.bridge.db.sqlite.SQLQuery;
-/**
+/*
* Created by Winston on 21/02/15.
*/
public class GetProjectNamesSQLQuery implements SQLQuery> {
- private static final String GET_URL_INDEXES_FOR_PROJECT_NAME =
- "SELECT `name` FROM `projects`";
+ private static final String GET_URL_INDEXES_FOR_PROJECT_NAME = "SELECT `name` FROM `projects`";
- @Override
- public List processResultSet(
- ResultSet resultSet
- ) throws SQLException {
- List projectNames = new ArrayList<>();
- while (resultSet.next()) {
- projectNames.add(resultSet.getString("name"));
- }
- return projectNames;
- }
-
- @Override
- public String getSQL() {
- return GET_URL_INDEXES_FOR_PROJECT_NAME;
+ @Override
+ public List processResultSet(ResultSet resultSet) throws SQLException {
+ List projectNames = new ArrayList<>();
+ while (resultSet.next()) {
+ projectNames.add(resultSet.getString("name"));
}
+ return projectNames;
+ }
+ @Override
+ public String getSQL() {
+ return GET_URL_INDEXES_FOR_PROJECT_NAME;
+ }
}
diff --git a/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/db/sqlite/query/GetProjectState.java b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/db/sqlite/query/GetProjectState.java
index 0120289e89..a291695818 100644
--- a/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/db/sqlite/query/GetProjectState.java
+++ b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/db/sqlite/query/GetProjectState.java
@@ -1,51 +1,43 @@
package uk.ac.ic.wlgitbridge.bridge.db.sqlite.query;
-import uk.ac.ic.wlgitbridge.bridge.db.ProjectState;
-import uk.ac.ic.wlgitbridge.bridge.db.sqlite.SQLQuery;
-
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
+import uk.ac.ic.wlgitbridge.bridge.db.ProjectState;
+import uk.ac.ic.wlgitbridge.bridge.db.sqlite.SQLQuery;
-/**
+/*
* Created by winston on 24/08/2016.
*/
public class GetProjectState implements SQLQuery {
- private static final String GET_PROJECT_STATE =
- "SELECT `last_accessed`\n" +
- " FROM `projects`\n" +
- " WHERE `name` = ?";
+ private static final String GET_PROJECT_STATE =
+ "SELECT `last_accessed`\n" + " FROM `projects`\n" + " WHERE `name` = ?";
- private final String projectName;
+ private final String projectName;
- public GetProjectState(String projectName) {
- this.projectName = projectName;
- }
-
- @Override
- public String getSQL() {
- return GET_PROJECT_STATE;
- }
-
- @Override
- public ProjectState processResultSet(
- ResultSet resultSet
- ) throws SQLException {
- while (resultSet.next()) {
- if (resultSet.getTimestamp("last_accessed") == null) {
- return ProjectState.SWAPPED;
- }
- return ProjectState.PRESENT;
- }
- return ProjectState.NOT_PRESENT;
- }
-
- @Override
- public void addParametersToStatement(
- PreparedStatement statement
- ) throws SQLException {
- statement.setString(1, projectName);
+ public GetProjectState(String projectName) {
+ this.projectName = projectName;
+ }
+
+ @Override
+ public String getSQL() {
+ return GET_PROJECT_STATE;
+ }
+
+ @Override
+ public ProjectState processResultSet(ResultSet resultSet) throws SQLException {
+ while (resultSet.next()) {
+ if (resultSet.getTimestamp("last_accessed") == null) {
+ return ProjectState.SWAPPED;
+ }
+ return ProjectState.PRESENT;
}
+ return ProjectState.NOT_PRESENT;
+ }
+ @Override
+ public void addParametersToStatement(PreparedStatement statement) throws SQLException {
+ statement.setString(1, projectName);
+ }
}
diff --git a/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/db/sqlite/query/GetSwapCompression.java b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/db/sqlite/query/GetSwapCompression.java
index c7f4d5b510..b21ec3e786 100644
--- a/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/db/sqlite/query/GetSwapCompression.java
+++ b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/db/sqlite/query/GetSwapCompression.java
@@ -1,14 +1,13 @@
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 uk.ac.ic.wlgitbridge.bridge.db.sqlite.SQLQuery;
public class GetSwapCompression implements SQLQuery {
private static final String GET_SWAP_COMPRESSION =
- "SELECT `swap_compression` FROM `projects` WHERE `name` = ?";
+ "SELECT `swap_compression` FROM `projects` WHERE `name` = ?";
private final String projectName;
@@ -31,9 +30,7 @@ public class GetSwapCompression implements SQLQuery {
}
@Override
- public void addParametersToStatement(
- PreparedStatement statement
- ) throws SQLException {
+ public void addParametersToStatement(PreparedStatement statement) throws SQLException {
statement.setString(1, projectName);
}
}
diff --git a/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/db/sqlite/query/LastAccessedColumnExists.java b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/db/sqlite/query/LastAccessedColumnExists.java
index da3b525ff3..758a47b21a 100644
--- a/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/db/sqlite/query/LastAccessedColumnExists.java
+++ b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/db/sqlite/query/LastAccessedColumnExists.java
@@ -1,31 +1,28 @@
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;
+import uk.ac.ic.wlgitbridge.bridge.db.sqlite.SQLQuery;
-/**
+/*
* Created by winston on 04/09/2016.
*/
public class LastAccessedColumnExists implements SQLQuery {
- private static final String LAST_ACCESSED_COLUMN_EXISTS =
- "PRAGMA table_info(`projects`)";
+ private static final String LAST_ACCESSED_COLUMN_EXISTS = "PRAGMA table_info(`projects`)";
- @Override
- public String getSQL() {
- return LAST_ACCESSED_COLUMN_EXISTS;
+ @Override
+ public String getSQL() {
+ return LAST_ACCESSED_COLUMN_EXISTS;
+ }
+
+ @Override
+ public Boolean processResultSet(ResultSet resultSet) throws SQLException {
+ while (resultSet.next()) {
+ if (resultSet.getString(2).equals("last_accessed")) {
+ return true;
+ }
}
-
- @Override
- public Boolean processResultSet(ResultSet resultSet) throws SQLException {
- while (resultSet.next()) {
- if (resultSet.getString(2).equals("last_accessed")) {
- return true;
- }
- }
- return false;
- }
-
+ return false;
+ }
}
diff --git a/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/db/sqlite/query/RestoreTimeColumnExists.java b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/db/sqlite/query/RestoreTimeColumnExists.java
index ed4d0567ae..c726bec2de 100644
--- a/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/db/sqlite/query/RestoreTimeColumnExists.java
+++ b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/db/sqlite/query/RestoreTimeColumnExists.java
@@ -1,26 +1,24 @@
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;
+import uk.ac.ic.wlgitbridge.bridge.db.sqlite.SQLQuery;
public class RestoreTimeColumnExists implements SQLQuery {
- private static final String RESTORE_TIME_COLUMN_EXISTS =
- "PRAGMA table_info(`projects`)";
+ private static final String RESTORE_TIME_COLUMN_EXISTS = "PRAGMA table_info(`projects`)";
- @Override
- public String getSQL() {
- return RESTORE_TIME_COLUMN_EXISTS;
- }
+ @Override
+ public String getSQL() {
+ return RESTORE_TIME_COLUMN_EXISTS;
+ }
- @Override
- public Boolean processResultSet(ResultSet resultSet) throws SQLException {
- while (resultSet.next()) {
- if (resultSet.getString(2).equals("restore_time")) {
- return true;
- }
- }
- return false;
+ @Override
+ public Boolean processResultSet(ResultSet resultSet) throws SQLException {
+ while (resultSet.next()) {
+ if (resultSet.getString(2).equals("restore_time")) {
+ return true;
+ }
}
+ return false;
+ }
}
diff --git a/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/db/sqlite/query/SwapCompressionColumnExists.java b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/db/sqlite/query/SwapCompressionColumnExists.java
index 1b1754f26e..89f083a5d5 100644
--- a/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/db/sqlite/query/SwapCompressionColumnExists.java
+++ b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/db/sqlite/query/SwapCompressionColumnExists.java
@@ -1,27 +1,24 @@
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;
+import uk.ac.ic.wlgitbridge.bridge.db.sqlite.SQLQuery;
public class SwapCompressionColumnExists implements SQLQuery {
- private static final String SWAP_COMPRESSION_COLUMN_EXISTS =
- "PRAGMA table_info(`projects`)";
+ private static final String SWAP_COMPRESSION_COLUMN_EXISTS = "PRAGMA table_info(`projects`)";
- @Override
- public String getSQL() {
- return SWAP_COMPRESSION_COLUMN_EXISTS;
+ @Override
+ public String getSQL() {
+ return SWAP_COMPRESSION_COLUMN_EXISTS;
+ }
+
+ @Override
+ public Boolean processResultSet(ResultSet resultSet) throws SQLException {
+ while (resultSet.next()) {
+ if (resultSet.getString(2).equals("swap_compression")) {
+ return true;
+ }
}
-
- @Override
- public Boolean processResultSet(ResultSet resultSet) throws SQLException {
- while (resultSet.next()) {
- if (resultSet.getString(2).equals("swap_compression")) {
- return true;
- }
- }
- return false;
- }
-
+ return false;
+ }
}
diff --git a/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/db/sqlite/query/SwapTimeColumnExists.java b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/db/sqlite/query/SwapTimeColumnExists.java
index 9426dedc5f..7d65e21bb2 100644
--- a/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/db/sqlite/query/SwapTimeColumnExists.java
+++ b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/db/sqlite/query/SwapTimeColumnExists.java
@@ -1,27 +1,24 @@
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;
+import uk.ac.ic.wlgitbridge.bridge.db.sqlite.SQLQuery;
public class SwapTimeColumnExists implements SQLQuery {
- private static final String SWAP_TIME_COLUMN_EXISTS =
- "PRAGMA table_info(`projects`)";
+ private static final String SWAP_TIME_COLUMN_EXISTS = "PRAGMA table_info(`projects`)";
- @Override
- public String getSQL() {
- return SWAP_TIME_COLUMN_EXISTS;
+ @Override
+ public String getSQL() {
+ return SWAP_TIME_COLUMN_EXISTS;
+ }
+
+ @Override
+ public Boolean processResultSet(ResultSet resultSet) throws SQLException {
+ while (resultSet.next()) {
+ if (resultSet.getString(2).equals("swap_time")) {
+ return true;
+ }
}
-
- @Override
- public Boolean processResultSet(ResultSet resultSet) throws SQLException {
- while (resultSet.next()) {
- if (resultSet.getString(2).equals("swap_time")) {
- return true;
- }
- }
- return false;
- }
-
+ return false;
+ }
}
diff --git a/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/db/sqlite/update/alter/ProjectsAddLastAccessed.java b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/db/sqlite/update/alter/ProjectsAddLastAccessed.java
index 549d4403b2..31bbadbd0c 100644
--- a/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/db/sqlite/update/alter/ProjectsAddLastAccessed.java
+++ b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/db/sqlite/update/alter/ProjectsAddLastAccessed.java
@@ -2,18 +2,16 @@ package uk.ac.ic.wlgitbridge.bridge.db.sqlite.update.alter;
import uk.ac.ic.wlgitbridge.bridge.db.sqlite.SQLUpdate;
-/**
+/*
* Created by winston on 03/09/2016.
*/
public class ProjectsAddLastAccessed implements SQLUpdate {
- private static final String PROJECTS_ADD_LAST_ACCESSED =
- "ALTER TABLE `projects`\n" +
- "ADD COLUMN `last_accessed` DATETIME NULL DEFAULT 0";
-
- @Override
- public String getSQL() {
- return PROJECTS_ADD_LAST_ACCESSED;
- }
+ private static final String PROJECTS_ADD_LAST_ACCESSED =
+ "ALTER TABLE `projects`\n" + "ADD COLUMN `last_accessed` DATETIME NULL DEFAULT 0";
+ @Override
+ public String getSQL() {
+ return PROJECTS_ADD_LAST_ACCESSED;
+ }
}
diff --git a/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/db/sqlite/update/alter/ProjectsAddRestoreTime.java b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/db/sqlite/update/alter/ProjectsAddRestoreTime.java
index dd92efcab5..d4675db1d0 100644
--- a/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/db/sqlite/update/alter/ProjectsAddRestoreTime.java
+++ b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/db/sqlite/update/alter/ProjectsAddRestoreTime.java
@@ -4,8 +4,7 @@ import uk.ac.ic.wlgitbridge.bridge.db.sqlite.SQLUpdate;
public class ProjectsAddRestoreTime implements SQLUpdate {
private static final String PROJECTS_ADD_RESTORE_TIME =
- "ALTER TABLE `projects`\n" +
- "ADD COLUMN `restore_time` DATETIME NULL;\n";
+ "ALTER TABLE `projects`\n" + "ADD COLUMN `restore_time` DATETIME NULL;\n";
@Override
public String getSQL() {
diff --git a/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/db/sqlite/update/alter/ProjectsAddSwapCompression.java b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/db/sqlite/update/alter/ProjectsAddSwapCompression.java
index c5599d9116..25ec93048b 100644
--- a/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/db/sqlite/update/alter/ProjectsAddSwapCompression.java
+++ b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/db/sqlite/update/alter/ProjectsAddSwapCompression.java
@@ -4,8 +4,7 @@ import uk.ac.ic.wlgitbridge.bridge.db.sqlite.SQLUpdate;
public class ProjectsAddSwapCompression implements SQLUpdate {
private static final String PROJECTS_ADD_SWAP_COMPRESSION =
- "ALTER TABLE `projects`\n" +
- "ADD COLUMN `swap_compression` VARCHAR NULL;\n";
+ "ALTER TABLE `projects`\n" + "ADD COLUMN `swap_compression` VARCHAR NULL;\n";
@Override
public String getSQL() {
diff --git a/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/db/sqlite/update/alter/ProjectsAddSwapTime.java b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/db/sqlite/update/alter/ProjectsAddSwapTime.java
index da89be8c25..e578dc0c9a 100644
--- a/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/db/sqlite/update/alter/ProjectsAddSwapTime.java
+++ b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/db/sqlite/update/alter/ProjectsAddSwapTime.java
@@ -4,12 +4,10 @@ import uk.ac.ic.wlgitbridge.bridge.db.sqlite.SQLUpdate;
public class ProjectsAddSwapTime implements SQLUpdate {
private static final String PROJECTS_ADD_SWAP_TIME =
- "ALTER TABLE `projects`\n" +
- "ADD COLUMN `swap_time` DATETIME NULL;\n";
+ "ALTER TABLE `projects`\n" + "ADD COLUMN `swap_time` DATETIME NULL;\n";
@Override
public String getSQL() {
return PROJECTS_ADD_SWAP_TIME;
}
-
}
diff --git a/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/db/sqlite/update/alter/SetSoftHeapLimitPragma.java b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/db/sqlite/update/alter/SetSoftHeapLimitPragma.java
index da1a98cfa5..0f8d935274 100644
--- a/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/db/sqlite/update/alter/SetSoftHeapLimitPragma.java
+++ b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/db/sqlite/update/alter/SetSoftHeapLimitPragma.java
@@ -3,15 +3,14 @@ package uk.ac.ic.wlgitbridge.bridge.db.sqlite.update.alter;
import uk.ac.ic.wlgitbridge.bridge.db.sqlite.SQLUpdate;
public class SetSoftHeapLimitPragma implements SQLUpdate {
- private int heapLimitBytes = 0;
+ private int heapLimitBytes = 0;
- public SetSoftHeapLimitPragma(int heapLimitBytes) {
- this.heapLimitBytes = heapLimitBytes;
- }
-
- @Override
- public String getSQL() {
- return "PRAGMA soft_heap_limit="+this.heapLimitBytes+";";
- }
+ public SetSoftHeapLimitPragma(int heapLimitBytes) {
+ this.heapLimitBytes = heapLimitBytes;
+ }
+ @Override
+ public String getSQL() {
+ return "PRAGMA soft_heap_limit=" + this.heapLimitBytes + ";";
+ }
}
diff --git a/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/db/sqlite/update/create/CreateIndexURLIndexStore.java b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/db/sqlite/update/create/CreateIndexURLIndexStore.java
index 9b89199b65..a40842227f 100644
--- a/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/db/sqlite/update/create/CreateIndexURLIndexStore.java
+++ b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/db/sqlite/update/create/CreateIndexURLIndexStore.java
@@ -2,18 +2,17 @@ package uk.ac.ic.wlgitbridge.bridge.db.sqlite.update.create;
import uk.ac.ic.wlgitbridge.bridge.db.sqlite.SQLUpdate;
-/**
+/*
* 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";
-
- @Override
- public String getSQL() {
- return CREATE_INDEX_URL_INDEX_STORE;
- }
+ 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";
+ @Override
+ public String getSQL() {
+ return CREATE_INDEX_URL_INDEX_STORE;
+ }
}
diff --git a/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/db/sqlite/update/create/CreateProjectsIndexLastAccessed.java b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/db/sqlite/update/create/CreateProjectsIndexLastAccessed.java
index 6e129d8fee..f937fa3b63 100644
--- a/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/db/sqlite/update/create/CreateProjectsIndexLastAccessed.java
+++ b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/db/sqlite/update/create/CreateProjectsIndexLastAccessed.java
@@ -2,18 +2,17 @@ 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 CreateProjectsIndexLastAccessed implements SQLUpdate {
- private static final String CREATE_PROJECTS_INDEX_LAST_ACCESSED =
- "CREATE INDEX IF NOT EXISTS `projects_index_last_accessed`\n" +
- " ON `projects`(`last_accessed`)";
-
- @Override
- public String getSQL() {
- return CREATE_PROJECTS_INDEX_LAST_ACCESSED;
- }
+ private static final String CREATE_PROJECTS_INDEX_LAST_ACCESSED =
+ "CREATE INDEX IF NOT EXISTS `projects_index_last_accessed`\n"
+ + " ON `projects`(`last_accessed`)";
+ @Override
+ public String getSQL() {
+ return CREATE_PROJECTS_INDEX_LAST_ACCESSED;
+ }
}
diff --git a/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/db/sqlite/update/create/CreateProjectsTableSQLUpdate.java b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/db/sqlite/update/create/CreateProjectsTableSQLUpdate.java
index 15042445ad..1e7910c247 100644
--- a/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/db/sqlite/update/create/CreateProjectsTableSQLUpdate.java
+++ b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/db/sqlite/update/create/CreateProjectsTableSQLUpdate.java
@@ -2,25 +2,24 @@ package uk.ac.ic.wlgitbridge.bridge.db.sqlite.update.create;
import uk.ac.ic.wlgitbridge.bridge.db.sqlite.SQLUpdate;
-/**
+/*
* Created by Winston on 20/11/14.
*/
public class CreateProjectsTableSQLUpdate implements SQLUpdate {
- private static final String CREATE_PROJECTS_TABLE =
- "CREATE TABLE IF NOT EXISTS `projects` (\n" +
- " `name` VARCHAR NOT NULL DEFAULT '',\n" +
- " `version_id` INT NOT NULL DEFAULT 0,\n" +
- " `last_accessed` DATETIME NULL DEFAULT 0,\n" +
- " `swap_time` DATETIME NULL,\n" +
- " `restore_time` DATETIME NULL,\n" +
- " `swap_compression` VARCHAR NULL,\n" +
- " PRIMARY KEY (`name`)\n" +
- ")";
-
- @Override
- public String getSQL() {
- return CREATE_PROJECTS_TABLE;
- }
+ private static final String CREATE_PROJECTS_TABLE =
+ "CREATE TABLE IF NOT EXISTS `projects` (\n"
+ + " `name` VARCHAR NOT NULL DEFAULT '',\n"
+ + " `version_id` INT NOT NULL DEFAULT 0,\n"
+ + " `last_accessed` DATETIME NULL DEFAULT 0,\n"
+ + " `swap_time` DATETIME NULL,\n"
+ + " `restore_time` DATETIME NULL,\n"
+ + " `swap_compression` VARCHAR NULL,\n"
+ + " PRIMARY KEY (`name`)\n"
+ + ")";
+ @Override
+ public String getSQL() {
+ return CREATE_PROJECTS_TABLE;
+ }
}
diff --git a/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/db/sqlite/update/create/CreateURLIndexStoreSQLUpdate.java b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/db/sqlite/update/create/CreateURLIndexStoreSQLUpdate.java
index 3ca0e9cf4c..1274eb0a59 100644
--- a/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/db/sqlite/update/create/CreateURLIndexStoreSQLUpdate.java
+++ b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/db/sqlite/update/create/CreateURLIndexStoreSQLUpdate.java
@@ -2,27 +2,26 @@ package uk.ac.ic.wlgitbridge.bridge.db.sqlite.update.create;
import uk.ac.ic.wlgitbridge.bridge.db.sqlite.SQLUpdate;
-/**
+/*
* Created by Winston on 20/11/14.
*/
public class CreateURLIndexStoreSQLUpdate implements SQLUpdate {
- private static final String CREATE_URL_INDEX_STORE =
- "CREATE TABLE IF NOT EXISTS `url_index_store` (\n"+
- " `project_name` varchar(10) NOT NULL DEFAULT '',\n"+
- " `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"+
- ");\n";
-
- @Override
- public String getSQL() {
- return CREATE_URL_INDEX_STORE;
- }
+ private static final String CREATE_URL_INDEX_STORE =
+ "CREATE TABLE IF NOT EXISTS `url_index_store` (\n"
+ + " `project_name` varchar(10) NOT NULL DEFAULT '',\n"
+ + " `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"
+ + ");\n";
+ @Override
+ public String getSQL() {
+ return CREATE_URL_INDEX_STORE;
+ }
}
diff --git a/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/db/sqlite/update/delete/DeleteAllFilesInProjectSQLUpdate.java b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/db/sqlite/update/delete/DeleteAllFilesInProjectSQLUpdate.java
index dd6e15daed..a23a468fcc 100644
--- a/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/db/sqlite/update/delete/DeleteAllFilesInProjectSQLUpdate.java
+++ b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/db/sqlite/update/delete/DeleteAllFilesInProjectSQLUpdate.java
@@ -2,7 +2,6 @@ package uk.ac.ic.wlgitbridge.bridge.db.sqlite.update.delete;
import java.sql.PreparedStatement;
import java.sql.SQLException;
-
import uk.ac.ic.wlgitbridge.bridge.db.sqlite.SQLUpdate;
public class DeleteAllFilesInProjectSQLUpdate implements SQLUpdate {
diff --git a/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/db/sqlite/update/delete/DeleteFilesForProjectSQLUpdate.java b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/db/sqlite/update/delete/DeleteFilesForProjectSQLUpdate.java
index 4390ebe9a0..5c3527a2ec 100644
--- a/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/db/sqlite/update/delete/DeleteFilesForProjectSQLUpdate.java
+++ b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/db/sqlite/update/delete/DeleteFilesForProjectSQLUpdate.java
@@ -1,53 +1,43 @@
package uk.ac.ic.wlgitbridge.bridge.db.sqlite.update.delete;
-import uk.ac.ic.wlgitbridge.bridge.db.sqlite.SQLUpdate;
-
import java.sql.PreparedStatement;
import java.sql.SQLException;
+import uk.ac.ic.wlgitbridge.bridge.db.sqlite.SQLUpdate;
-/**
+/*
* Created by Winston on 20/11/14.
*/
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 (";
+ private static final String DELETE_URL_INDEXES_FOR_PROJECT_NAME =
+ "DELETE FROM `url_index_store` " + "WHERE `project_name` = ? AND path IN (";
- private final String projectName;
- private final String[] paths;
+ private final String projectName;
+ private final String[] paths;
- public DeleteFilesForProjectSQLUpdate(
- String projectName,
- String... paths
- ) {
- this.projectName = projectName;
- this.paths = paths;
+ public DeleteFilesForProjectSQLUpdate(String projectName, String... paths) {
+ this.projectName = projectName;
+ this.paths = paths;
+ }
+
+ @Override
+ public String getSQL() {
+ 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) {
+ sb.append(", ");
+ }
}
+ sb.append(");\n");
+ return sb.toString();
+ }
- @Override
- public String getSQL() {
- 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) {
- sb.append(", ");
- }
- }
- sb.append(");\n");
- return sb.toString();
+ @Override
+ 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]);
}
-
- @Override
- 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]);
- }
- }
-
+ }
}
diff --git a/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/db/sqlite/update/delete/DeleteProjectSQLUpdate.java b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/db/sqlite/update/delete/DeleteProjectSQLUpdate.java
index 64153cf504..ff989e16c1 100644
--- a/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/db/sqlite/update/delete/DeleteProjectSQLUpdate.java
+++ b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/db/sqlite/update/delete/DeleteProjectSQLUpdate.java
@@ -2,7 +2,6 @@ package uk.ac.ic.wlgitbridge.bridge.db.sqlite.update.delete;
import java.sql.PreparedStatement;
import java.sql.SQLException;
-
import uk.ac.ic.wlgitbridge.bridge.db.sqlite.SQLUpdate;
public class DeleteProjectSQLUpdate implements SQLUpdate {
diff --git a/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/db/sqlite/update/insert/AddURLIndexSQLUpdate.java b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/db/sqlite/update/insert/AddURLIndexSQLUpdate.java
index 5c337bed7a..a79ea6d078 100644
--- a/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/db/sqlite/update/insert/AddURLIndexSQLUpdate.java
+++ b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/db/sqlite/update/insert/AddURLIndexSQLUpdate.java
@@ -1,45 +1,41 @@
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 uk.ac.ic.wlgitbridge.bridge.db.sqlite.SQLUpdate;
-/**
+/*
* Created by Winston on 20/11/14.
*/
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";
+ private static final String ADD_URL_INDEX =
+ "INSERT OR REPLACE INTO `url_index_store`("
+ + "`project_name`, "
+ + "`url`, "
+ + "`path`"
+ + ") VALUES "
+ + "(?, ?, ?)\n";
- private final String projectName;
- private final String url;
- private final String path;
+ private final String projectName;
+ private final String url;
+ private final String path;
- public AddURLIndexSQLUpdate(String projectName, String url, String path) {
- this.projectName = projectName;
- this.url = url;
- this.path = path;
- }
+ public AddURLIndexSQLUpdate(String projectName, String url, String path) {
+ this.projectName = projectName;
+ this.url = url;
+ this.path = path;
+ }
- @Override
- public String getSQL() {
- return ADD_URL_INDEX;
- }
-
- @Override
- public void addParametersToStatement(
- PreparedStatement statement
- ) throws SQLException {
- statement.setString(1, projectName);
- statement.setString(2, url);
- statement.setString(3, path);
- }
+ @Override
+ public String getSQL() {
+ return ADD_URL_INDEX;
+ }
+ @Override
+ public void addParametersToStatement(PreparedStatement statement) throws SQLException {
+ statement.setString(1, projectName);
+ statement.setString(2, url);
+ statement.setString(3, path);
+ }
}
diff --git a/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/db/sqlite/update/insert/SetProjectLastAccessedTime.java b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/db/sqlite/update/insert/SetProjectLastAccessedTime.java
index 7870822a50..945f3988d1 100644
--- a/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/db/sqlite/update/insert/SetProjectLastAccessedTime.java
+++ b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/db/sqlite/update/insert/SetProjectLastAccessedTime.java
@@ -1,43 +1,34 @@
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;
+import uk.ac.ic.wlgitbridge.bridge.db.sqlite.SQLUpdate;
-/**
+/*
* Created by winston on 23/08/2016.
*/
public class SetProjectLastAccessedTime implements SQLUpdate {
- private static final String SET_PROJECT_LAST_ACCESSED_TIME =
- "UPDATE `projects`\n" +
- "SET `last_accessed` = ?\n" +
- "WHERE `name` = ?";
+ private static final String SET_PROJECT_LAST_ACCESSED_TIME =
+ "UPDATE `projects`\n" + "SET `last_accessed` = ?\n" + "WHERE `name` = ?";
- private final String projectName;
- private final Timestamp lastAccessed;
+ private final String projectName;
+ private final Timestamp lastAccessed;
- public SetProjectLastAccessedTime(
- String projectName,
- Timestamp lastAccessed
- ) {
- this.projectName = projectName;
- this.lastAccessed = 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.setTimestamp(1, lastAccessed);
- statement.setString(2, projectName);
- }
+ @Override
+ public String getSQL() {
+ return SET_PROJECT_LAST_ACCESSED_TIME;
+ }
+ @Override
+ public void addParametersToStatement(PreparedStatement statement) throws SQLException {
+ statement.setTimestamp(1, lastAccessed);
+ statement.setString(2, projectName);
+ }
}
diff --git a/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/db/sqlite/update/insert/SetProjectSQLUpdate.java b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/db/sqlite/update/insert/SetProjectSQLUpdate.java
index 717beaec05..7c472e0fb7 100644
--- a/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/db/sqlite/update/insert/SetProjectSQLUpdate.java
+++ b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/db/sqlite/update/insert/SetProjectSQLUpdate.java
@@ -1,39 +1,35 @@
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 uk.ac.ic.wlgitbridge.bridge.db.sqlite.SQLUpdate;
-/**
+/*
* Created by Winston on 20/11/14.
*/
public class SetProjectSQLUpdate implements SQLUpdate {
- private static final String SET_PROJECT =
- "INSERT OR REPLACE "
- + "INTO `projects`(`name`, `version_id`, `last_accessed`) "
- + "VALUES (?, ?, DATETIME('now'));\n";
+ private static final String SET_PROJECT =
+ "INSERT OR REPLACE "
+ + "INTO `projects`(`name`, `version_id`, `last_accessed`) "
+ + "VALUES (?, ?, DATETIME('now'));\n";
- private final String projectName;
- private final int versionID;
+ private final String projectName;
+ private final int versionID;
- public SetProjectSQLUpdate(String projectName, int versionID) {
- this.projectName = projectName;
- this.versionID = versionID;
- }
+ public SetProjectSQLUpdate(String projectName, int versionID) {
+ this.projectName = projectName;
+ this.versionID = versionID;
+ }
- @Override
- public String getSQL() {
- return SET_PROJECT;
- }
-
- @Override
- public void addParametersToStatement(
- PreparedStatement statement
- ) throws SQLException {
- statement.setString(1, projectName);
- statement.setInt(2, versionID);
- }
+ @Override
+ public String getSQL() {
+ return SET_PROJECT;
+ }
+ @Override
+ public void addParametersToStatement(PreparedStatement statement) throws SQLException {
+ statement.setString(1, projectName);
+ statement.setInt(2, versionID);
+ }
}
diff --git a/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/db/sqlite/update/insert/UpdateRestore.java b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/db/sqlite/update/insert/UpdateRestore.java
index 91abc5f473..bb76748b6c 100644
--- a/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/db/sqlite/update/insert/UpdateRestore.java
+++ b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/db/sqlite/update/insert/UpdateRestore.java
@@ -1,20 +1,19 @@
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;
import java.time.LocalDateTime;
+import uk.ac.ic.wlgitbridge.bridge.db.sqlite.SQLUpdate;
public class UpdateRestore implements SQLUpdate {
private static final String UPDATE_RESTORE =
- "UPDATE `projects`\n" +
- "SET `last_accessed` = ?,\n" +
- " `swap_time` = NULL,\n" +
- " `restore_time` = ?,\n" +
- " `swap_compression` = NULL\n" +
- "WHERE `name` = ?;\n";
+ "UPDATE `projects`\n"
+ + "SET `last_accessed` = ?,\n"
+ + " `swap_time` = NULL,\n"
+ + " `restore_time` = ?,\n"
+ + " `swap_compression` = NULL\n"
+ + "WHERE `name` = ?;\n";
private final String projectName;
private final Timestamp now;
@@ -30,9 +29,7 @@ public class UpdateRestore implements SQLUpdate {
}
@Override
- public void addParametersToStatement(
- PreparedStatement statement
- ) throws SQLException {
+ public void addParametersToStatement(PreparedStatement statement) throws SQLException {
statement.setTimestamp(1, now);
statement.setTimestamp(2, now);
statement.setString(3, projectName);
diff --git a/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/db/sqlite/update/insert/UpdateSwap.java b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/db/sqlite/update/insert/UpdateSwap.java
index 24d7815279..df09ddcdf6 100644
--- a/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/db/sqlite/update/insert/UpdateSwap.java
+++ b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/db/sqlite/update/insert/UpdateSwap.java
@@ -1,20 +1,19 @@
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;
import java.time.LocalDateTime;
+import uk.ac.ic.wlgitbridge.bridge.db.sqlite.SQLUpdate;
public class UpdateSwap implements SQLUpdate {
private static final String UPDATE_SWAP =
- "UPDATE `projects`\n" +
- "SET `last_accessed` = NULL,\n" +
- " `swap_time` = ?,\n" +
- " `restore_time` = NULL,\n" +
- " `swap_compression` = ?\n" +
- "WHERE `name` = ?;\n";
+ "UPDATE `projects`\n"
+ + "SET `last_accessed` = NULL,\n"
+ + " `swap_time` = ?,\n"
+ + " `restore_time` = NULL,\n"
+ + " `swap_compression` = ?\n"
+ + "WHERE `name` = ?;\n";
private final String projectName;
private final String compression;
@@ -32,9 +31,7 @@ public class UpdateSwap implements SQLUpdate {
}
@Override
- public void addParametersToStatement(
- PreparedStatement statement
- ) throws SQLException {
+ public void addParametersToStatement(PreparedStatement statement) throws SQLException {
statement.setTimestamp(1, now);
statement.setString(2, compression);
statement.setString(3, projectName);
diff --git a/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/gc/GcJob.java b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/gc/GcJob.java
index 74f965d7a4..60edc7a268 100644
--- a/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/gc/GcJob.java
+++ b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/gc/GcJob.java
@@ -1,13 +1,8 @@
package uk.ac.ic.wlgitbridge.bridge.gc;
-import uk.ac.ic.wlgitbridge.bridge.Bridge;
-import uk.ac.ic.wlgitbridge.bridge.repo.ProjectRepo;
-import uk.ac.ic.wlgitbridge.data.filestore.RawDirectory;
-
-import java.util.Optional;
import java.util.concurrent.CompletableFuture;
-/**
+/*
* Is started by the bridge. Every time a project is updated, we queue it for
* GC which executes every hour or so.
*
@@ -20,15 +15,15 @@ import java.util.concurrent.CompletableFuture;
*/
public interface GcJob {
- void start();
+ void start();
- void stop();
+ void stop();
- void onPreGc(Runnable preGc);
+ void onPreGc(Runnable preGc);
- void onPostGc(Runnable postGc);
+ void onPostGc(Runnable postGc);
- void queueForGc(String projectName);
+ void queueForGc(String projectName);
- CompletableFuture waitForRun();
+ CompletableFuture waitForRun();
}
diff --git a/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/gc/GcJobImpl.java b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/gc/GcJobImpl.java
index 37b49432c1..6ccf1dd8a1 100644
--- a/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/gc/GcJobImpl.java
+++ b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/gc/GcJobImpl.java
@@ -1,13 +1,5 @@
package uk.ac.ic.wlgitbridge.bridge.gc;
-import uk.ac.ic.wlgitbridge.bridge.lock.LockGuard;
-import uk.ac.ic.wlgitbridge.bridge.lock.ProjectLock;
-import uk.ac.ic.wlgitbridge.bridge.repo.ProjectRepo;
-import uk.ac.ic.wlgitbridge.bridge.repo.RepoStore;
-import uk.ac.ic.wlgitbridge.data.CannotAcquireLockException;
-import uk.ac.ic.wlgitbridge.util.Log;
-import uk.ac.ic.wlgitbridge.util.TimerUtils;
-
import java.io.IOException;
import java.util.*;
import java.util.concurrent.CompletableFuture;
@@ -16,129 +8,123 @@ import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicReference;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
+import uk.ac.ic.wlgitbridge.bridge.lock.LockGuard;
+import uk.ac.ic.wlgitbridge.bridge.lock.ProjectLock;
+import uk.ac.ic.wlgitbridge.bridge.repo.ProjectRepo;
+import uk.ac.ic.wlgitbridge.bridge.repo.RepoStore;
+import uk.ac.ic.wlgitbridge.data.CannotAcquireLockException;
+import uk.ac.ic.wlgitbridge.util.Log;
+import uk.ac.ic.wlgitbridge.util.TimerUtils;
-/**
+/*
* Implementation of {@link GcJob} using its own Timer and a synchronized
* queue.
*/
public class GcJobImpl implements GcJob {
- private final RepoStore repoStore;
- private final ProjectLock locks;
+ private final RepoStore repoStore;
+ private final ProjectLock locks;
- private final long intervalMs;
- private final Timer timer;
+ private final long intervalMs;
+ private final Timer timer;
- private final Set gcQueue;
+ private final Set gcQueue;
- /**
- * Hooks in case they are needed, e.g. for testing.
- */
- private AtomicReference preGc;
- private AtomicReference postGc;
+ /*
+ * Hooks in case they are needed, e.g. for testing.
+ */
+ private AtomicReference preGc;
+ private AtomicReference postGc;
- /* We need to iterate over and empty it after every run */
- private final Lock jobWaitersLock;
- private final List> jobWaiters;
+ /* We need to iterate over and empty it after every run */
+ private final Lock jobWaitersLock;
+ private final List> jobWaiters;
- public GcJobImpl(RepoStore repoStore, ProjectLock locks, long intervalMs) {
- this.repoStore = repoStore;
- this.locks = locks;
- this.intervalMs = intervalMs;
- timer = new Timer();
- gcQueue = Collections.newSetFromMap(new ConcurrentHashMap<>());
- preGc = new AtomicReference<>(() -> {});
- postGc = new AtomicReference<>(() -> {});
- jobWaitersLock = new ReentrantLock();
- jobWaiters = new ArrayList<>();
+ public GcJobImpl(RepoStore repoStore, ProjectLock locks, long intervalMs) {
+ this.repoStore = repoStore;
+ this.locks = locks;
+ this.intervalMs = intervalMs;
+ timer = new Timer();
+ gcQueue = Collections.newSetFromMap(new ConcurrentHashMap<>());
+ preGc = new AtomicReference<>(() -> {});
+ postGc = new AtomicReference<>(() -> {});
+ jobWaitersLock = new ReentrantLock();
+ jobWaiters = new ArrayList<>();
+ }
+
+ public GcJobImpl(RepoStore repoStore, ProjectLock locks) {
+ this(repoStore, locks, TimeUnit.MILLISECONDS.convert(1, TimeUnit.HOURS));
+ }
+
+ @Override
+ public void start() {
+ Log.info("Starting GC job to run every [{}] ms", intervalMs);
+ timer.scheduleAtFixedRate(TimerUtils.makeTimerTask(this::doGC), intervalMs, intervalMs);
+ }
+
+ @Override
+ public void stop() {
+ Log.info("Stopping GC job");
+ timer.cancel();
+ }
+
+ @Override
+ public void onPreGc(Runnable preGc) {
+ this.preGc.set(preGc);
+ }
+
+ @Override
+ public void onPostGc(Runnable postGc) {
+ this.postGc.set(postGc);
+ }
+
+ /*
+ * Needs to be callable from any thread.
+ * @param projectName
+ */
+ @Override
+ public void queueForGc(String projectName) {
+ gcQueue.add(projectName);
+ }
+
+ @Override
+ public CompletableFuture waitForRun() {
+ CompletableFuture ret = new CompletableFuture<>();
+ jobWaitersLock.lock();
+ try {
+ jobWaiters.add(ret);
+ } finally {
+ jobWaitersLock.unlock();
}
+ return ret;
+ }
- public GcJobImpl(RepoStore repoStore, ProjectLock locks) {
- this(
- repoStore,
- locks,
- TimeUnit.MILLISECONDS.convert(1, TimeUnit.HOURS)
- );
- }
-
- @Override
- public void start() {
- Log.info("Starting GC job to run every [{}] ms", intervalMs);
- timer.scheduleAtFixedRate(
- TimerUtils.makeTimerTask(this::doGC),
- intervalMs,
- intervalMs
- );
- }
-
- @Override
- public void stop() {
- Log.info("Stopping GC job");
- timer.cancel();
- }
-
- @Override
- public void onPreGc(Runnable preGc) {
- this.preGc.set(preGc);
- }
-
- @Override
- public void onPostGc(Runnable postGc) {
- this.postGc.set(postGc);
- }
-
- /**
- * Needs to be callable from any thread.
- * @param projectName
- */
- @Override
- public void queueForGc(String projectName) {
- gcQueue.add(projectName);
- }
-
- @Override
- public CompletableFuture waitForRun() {
- CompletableFuture ret = new CompletableFuture<>();
- jobWaitersLock.lock();
+ private void doGC() {
+ Log.info("GC job running");
+ int numGcs = 0;
+ preGc.get().run();
+ for (Iterator it = gcQueue.iterator(); it.hasNext(); it.remove(), ++numGcs) {
+ String proj = it.next();
+ Log.debug("[{}] Running GC job on project", proj);
+ try (LockGuard __ = locks.lockGuard(proj)) {
try {
- jobWaiters.add(ret);
- } finally {
- jobWaitersLock.unlock();
+ ProjectRepo repo = repoStore.getExistingRepo(proj);
+ repo.runGC();
+ repo.deleteIncomingPacks();
+ } catch (IOException e) {
+ Log.warn("[{}] Failed to GC project", proj);
}
- return ret;
+ } catch (CannotAcquireLockException e) {
+ Log.warn("[{}] Cannot acquire project lock, skipping GC", proj);
+ }
}
-
- private void doGC() {
- Log.info("GC job running");
- int numGcs = 0;
- preGc.get().run();
- for (
- Iterator it = gcQueue.iterator();
- it.hasNext();
- it.remove(), ++numGcs
- ) {
- String proj = it.next();
- Log.debug("[{}] Running GC job on project", proj);
- try (LockGuard __ = locks.lockGuard(proj)) {
- try {
- ProjectRepo repo = repoStore.getExistingRepo(proj);
- repo.runGC();
- repo.deleteIncomingPacks();
- } catch (IOException e) {
- Log.warn("[{}] Failed to GC project", proj);
- }
- } catch (CannotAcquireLockException e) {
- Log.warn("[{}] Cannot acquire project lock, skipping GC", proj);
- }
- }
- Log.info("GC job finished, num gcs: {}", numGcs);
- jobWaitersLock.lock();
- try {
- jobWaiters.forEach(w -> w.complete(null));
- } finally {
- jobWaitersLock.unlock();
- }
- postGc.get().run();
+ Log.info("GC job finished, num gcs: {}", numGcs);
+ jobWaitersLock.lock();
+ try {
+ jobWaiters.forEach(w -> w.complete(null));
+ } finally {
+ jobWaitersLock.unlock();
}
-
+ postGc.get().run();
+ }
}
diff --git a/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/lock/LockGuard.java b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/lock/LockGuard.java
index 73c8d253c1..9fc761a7c2 100644
--- a/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/lock/LockGuard.java
+++ b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/lock/LockGuard.java
@@ -1,10 +1,9 @@
package uk.ac.ic.wlgitbridge.bridge.lock;
-/**
+/*
* Created by winston on 24/08/2016.
*/
public interface LockGuard extends AutoCloseable {
- void close();
-
+ void close();
}
diff --git a/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/lock/ProjectLock.java b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/lock/ProjectLock.java
index f4617d258c..e23c23c2e6 100644
--- a/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/lock/ProjectLock.java
+++ b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/lock/ProjectLock.java
@@ -2,7 +2,7 @@ package uk.ac.ic.wlgitbridge.bridge.lock;
import uk.ac.ic.wlgitbridge.data.CannotAcquireLockException;
-/**
+/*
* Project Lock class.
*
* The locks should be re-entrant. For example, we are usually holding the lock
@@ -10,16 +10,15 @@ import uk.ac.ic.wlgitbridge.data.CannotAcquireLockException;
*/
public interface ProjectLock {
- void lockAll();
+ void lockAll();
- void lockForProject(String projectName) throws CannotAcquireLockException;
+ void lockForProject(String projectName) throws CannotAcquireLockException;
- void unlockForProject(String projectName);
-
- /* RAII hahaha */
- default LockGuard lockGuard(String projectName) throws CannotAcquireLockException {
- lockForProject(projectName);
- return () -> unlockForProject(projectName);
- }
+ void unlockForProject(String projectName);
+ /* RAII hahaha */
+ default LockGuard lockGuard(String projectName) throws CannotAcquireLockException {
+ lockForProject(projectName);
+ return () -> unlockForProject(projectName);
+ }
}
diff --git a/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/repo/FSGitRepoStore.java b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/repo/FSGitRepoStore.java
index e2fadc05a0..d774f30652 100644
--- a/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/repo/FSGitRepoStore.java
+++ b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/repo/FSGitRepoStore.java
@@ -1,13 +1,8 @@
package uk.ac.ic.wlgitbridge.bridge.repo;
-import com.google.api.client.repackaged.com.google.common.base.Preconditions;
-import org.apache.commons.io.FileUtils;
-import org.eclipse.jgit.lib.ObjectId;
-import org.eclipse.jgit.lib.Repository;
-import uk.ac.ic.wlgitbridge.util.Log;
-import uk.ac.ic.wlgitbridge.util.Project;
-import uk.ac.ic.wlgitbridge.util.Tar;
+import static uk.ac.ic.wlgitbridge.util.Util.deleteInDirectoryApartFrom;
+import com.google.api.client.repackaged.com.google.common.base.Preconditions;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
@@ -17,201 +12,153 @@ import java.util.Collection;
import java.util.List;
import java.util.Optional;
import java.util.function.Function;
+import org.apache.commons.io.FileUtils;
+import org.eclipse.jgit.lib.ObjectId;
+import org.eclipse.jgit.lib.Repository;
+import uk.ac.ic.wlgitbridge.util.Log;
+import uk.ac.ic.wlgitbridge.util.Project;
+import uk.ac.ic.wlgitbridge.util.Tar;
-import static uk.ac.ic.wlgitbridge.util.Util.deleteInDirectoryApartFrom;
-
-/**
+/*
* Created by winston on 20/08/2016.
*/
public class FSGitRepoStore implements RepoStore {
- private static final long DEFAULT_MAX_FILE_SIZE = 50 * 1024 * 1024;
+ private static final long DEFAULT_MAX_FILE_SIZE = 50 * 1024 * 1024;
- private final String repoStorePath;
+ private final String repoStorePath;
- private final File rootDirectory;
+ private final File rootDirectory;
- private final long maxFileSize;
+ private final long maxFileSize;
- private final Function fsSizer;
+ private final Function fsSizer;
- public FSGitRepoStore(
- String repoStorePath,
- Optional maxFileSize
- ) {
- this(
- repoStorePath,
- maxFileSize.orElse(DEFAULT_MAX_FILE_SIZE),
- d -> d.getTotalSpace() - d.getFreeSpace()
- );
- }
+ public FSGitRepoStore(String repoStorePath, Optional maxFileSize) {
+ this(
+ repoStorePath,
+ maxFileSize.orElse(DEFAULT_MAX_FILE_SIZE),
+ d -> d.getTotalSpace() - d.getFreeSpace());
+ }
- public FSGitRepoStore(
- String repoStorePath,
- long maxFileSize,
- Function fsSizer
- ) {
- this.repoStorePath = repoStorePath;
- rootDirectory = initRootGitDirectory(repoStorePath);
- this.maxFileSize = maxFileSize;
- this.fsSizer = fsSizer;
- }
+ public FSGitRepoStore(String repoStorePath, long maxFileSize, Function fsSizer) {
+ this.repoStorePath = repoStorePath;
+ rootDirectory = initRootGitDirectory(repoStorePath);
+ this.maxFileSize = maxFileSize;
+ this.fsSizer = fsSizer;
+ }
- @Override
- public String getRepoStorePath() {
- return repoStorePath;
- }
+ @Override
+ public String getRepoStorePath() {
+ return repoStorePath;
+ }
- @Override
- public File getRootDirectory() {
- return rootDirectory;
- }
+ @Override
+ public File getRootDirectory() {
+ return rootDirectory;
+ }
- @Override
- public ProjectRepo initRepo(String project) throws IOException {
- GitProjectRepo ret = GitProjectRepo.fromName(project);
- ret.initRepo(this);
- return new WalkOverrideGitRepo(
- ret, Optional.of(maxFileSize), Optional.empty());
- }
+ @Override
+ public ProjectRepo initRepo(String project) throws IOException {
+ GitProjectRepo ret = GitProjectRepo.fromName(project);
+ ret.initRepo(this);
+ return new WalkOverrideGitRepo(ret, Optional.of(maxFileSize), Optional.empty());
+ }
- @Override
- public ProjectRepo getExistingRepo(String project) throws IOException {
- GitProjectRepo ret = GitProjectRepo.fromName(project);
- ret.useExistingRepository(this);
- return new WalkOverrideGitRepo(
- ret, Optional.of(maxFileSize), Optional.empty());
- }
+ @Override
+ public ProjectRepo getExistingRepo(String project) throws IOException {
+ GitProjectRepo ret = GitProjectRepo.fromName(project);
+ ret.useExistingRepository(this);
+ return new WalkOverrideGitRepo(ret, Optional.of(maxFileSize), Optional.empty());
+ }
- @Override
- public ProjectRepo useJGitRepo(Repository repo, ObjectId commitId) {
- GitProjectRepo ret = GitProjectRepo.fromJGitRepo(repo);
- return new WalkOverrideGitRepo(
- ret, Optional.of(maxFileSize), Optional.of(commitId));
- }
+ @Override
+ public ProjectRepo useJGitRepo(Repository repo, ObjectId commitId) {
+ GitProjectRepo ret = GitProjectRepo.fromJGitRepo(repo);
+ return new WalkOverrideGitRepo(ret, Optional.of(maxFileSize), Optional.of(commitId));
+ }
- /* TODO: Perhaps we should just delete bad directories on the fly. */
- @Override
- public void purgeNonexistentProjects(
- Collection existingProjectNames
- ) {
- List excludedFromDeletion =
- new ArrayList<>(existingProjectNames);
- excludedFromDeletion.add(".wlgb");
- deleteInDirectoryApartFrom(
- rootDirectory,
- excludedFromDeletion.toArray(new String[] {})
- );
- }
+ /* TODO: Perhaps we should just delete bad directories on the fly. */
+ @Override
+ public void purgeNonexistentProjects(Collection existingProjectNames) {
+ List excludedFromDeletion = new ArrayList<>(existingProjectNames);
+ excludedFromDeletion.add(".wlgb");
+ deleteInDirectoryApartFrom(rootDirectory, excludedFromDeletion.toArray(new String[] {}));
+ }
- @Override
- public long totalSize() {
- return fsSizer.apply(rootDirectory);
- }
+ @Override
+ public long totalSize() {
+ return fsSizer.apply(rootDirectory);
+ }
- @Override
- public InputStream bzip2Project(
- String projectName,
- long[] sizePtr
- ) throws IOException {
- Project.checkValidProjectName(projectName);
- Log.debug("[{}] bzip2 project", projectName);
- return Tar.bz2.zip(getDotGitForProject(projectName), sizePtr);
- }
+ @Override
+ public InputStream bzip2Project(String projectName, long[] sizePtr) throws IOException {
+ Project.checkValidProjectName(projectName);
+ Log.debug("[{}] bzip2 project", projectName);
+ return Tar.bz2.zip(getDotGitForProject(projectName), sizePtr);
+ }
- @Override
- public InputStream gzipProject(
- String projectName,
- long[] sizePtr
- ) throws IOException {
- Project.checkValidProjectName(projectName);
- Log.debug("[{}] gzip project", projectName);
- return Tar.gzip.zip(getDotGitForProject(projectName), sizePtr);
- }
+ @Override
+ public InputStream gzipProject(String projectName, long[] sizePtr) throws IOException {
+ Project.checkValidProjectName(projectName);
+ Log.debug("[{}] gzip project", projectName);
+ return Tar.gzip.zip(getDotGitForProject(projectName), sizePtr);
+ }
- @Override
- public void gcProject(String projectName) throws IOException {
- Project.checkValidProjectName(projectName);
- ProjectRepo repo = getExistingRepo(projectName);
- repo.runGC();
- }
+ @Override
+ public void gcProject(String projectName) throws IOException {
+ Project.checkValidProjectName(projectName);
+ ProjectRepo repo = getExistingRepo(projectName);
+ repo.runGC();
+ }
- @Override
- public void remove(String projectName) throws IOException {
- Project.checkValidProjectName(projectName);
- FileUtils.deleteDirectory(new File(rootDirectory, projectName));
- }
+ @Override
+ public void remove(String projectName) throws IOException {
+ Project.checkValidProjectName(projectName);
+ FileUtils.deleteDirectory(new File(rootDirectory, projectName));
+ }
- @Override
- public void unbzip2Project(
- String projectName,
- InputStream dataStream
- ) throws IOException {
- Preconditions.checkArgument(
- Project.isValidProjectName(projectName),
- "[%s] invalid project name: ",
- projectName
- );
- Preconditions.checkState(
- getDirForProject(projectName).mkdirs(),
- "[%s] directories for " +
- "evicted project already exist",
- projectName
- );
- Log.debug("[{}] un-bzip2 project", projectName);
- Tar.bz2.unzip(dataStream, getDirForProject(projectName));
- }
+ @Override
+ public void unbzip2Project(String projectName, InputStream dataStream) throws IOException {
+ Preconditions.checkArgument(
+ Project.isValidProjectName(projectName), "[%s] invalid project name: ", projectName);
+ Preconditions.checkState(
+ getDirForProject(projectName).mkdirs(),
+ "[%s] directories for " + "evicted project already exist",
+ projectName);
+ Log.debug("[{}] un-bzip2 project", projectName);
+ Tar.bz2.unzip(dataStream, getDirForProject(projectName));
+ }
- @Override
- public void ungzipProject(
- String projectName,
- InputStream dataStream
- ) throws IOException {
- Preconditions.checkArgument(
- Project.isValidProjectName(projectName),
- "[%s] invalid project name: ",
- projectName
- );
- Preconditions.checkState(
- getDirForProject(projectName).mkdirs(),
- "[%s] directories for " +
- "evicted project already exist",
- projectName
- );
- Log.debug("[{}] un-gzip project", projectName);
- Tar.gzip.unzip(dataStream, getDirForProject(projectName));
- }
+ @Override
+ public void ungzipProject(String projectName, InputStream dataStream) throws IOException {
+ Preconditions.checkArgument(
+ Project.isValidProjectName(projectName), "[%s] invalid project name: ", projectName);
+ Preconditions.checkState(
+ getDirForProject(projectName).mkdirs(),
+ "[%s] directories for " + "evicted project already exist",
+ projectName);
+ Log.debug("[{}] un-gzip project", projectName);
+ Tar.gzip.unzip(dataStream, getDirForProject(projectName));
+ }
- private File getDirForProject(String projectName) {
- Project.checkValidProjectName(projectName);
- return Paths.get(
- rootDirectory.getAbsolutePath()
- ).resolve(
- projectName
- ).toFile();
- }
+ private File getDirForProject(String projectName) {
+ Project.checkValidProjectName(projectName);
+ return Paths.get(rootDirectory.getAbsolutePath()).resolve(projectName).toFile();
+ }
- private File getDotGitForProject(String projectName) {
- Project.checkValidProjectName(projectName);
- return Paths.get(
- rootDirectory.getAbsolutePath()
- ).resolve(
- projectName
- ).resolve(
- ".git"
- ).toFile();
- }
-
- private File initRootGitDirectory(String rootGitDirectoryPath) {
- File rootGitDirectory = new File(rootGitDirectoryPath);
- rootGitDirectory.mkdirs();
- Preconditions.checkArgument(
- rootGitDirectory.isDirectory(),
- "given root git directory " +
- "is not a directory: %s",
- rootGitDirectory.getAbsolutePath()
- );
- return rootGitDirectory;
- }
+ private File getDotGitForProject(String projectName) {
+ Project.checkValidProjectName(projectName);
+ return Paths.get(rootDirectory.getAbsolutePath()).resolve(projectName).resolve(".git").toFile();
+ }
+ private File initRootGitDirectory(String rootGitDirectoryPath) {
+ File rootGitDirectory = new File(rootGitDirectoryPath);
+ rootGitDirectory.mkdirs();
+ Preconditions.checkArgument(
+ rootGitDirectory.isDirectory(),
+ "given root git directory " + "is not a directory: %s",
+ rootGitDirectory.getAbsolutePath());
+ return rootGitDirectory;
+ }
}
diff --git a/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/repo/GitProjectRepo.java b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/repo/GitProjectRepo.java
index 4f37b9eab6..86754f8ab4 100644
--- a/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/repo/GitProjectRepo.java
+++ b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/repo/GitProjectRepo.java
@@ -1,6 +1,15 @@
package uk.ac.ic.wlgitbridge.bridge.repo;
import com.google.common.base.Preconditions;
+import java.io.File;
+import java.io.IOException;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.FileVisitResult;
+import java.nio.file.FileVisitor;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.attribute.BasicFileAttributes;
+import java.util.*;
import org.apache.commons.io.IOUtils;
import org.eclipse.jgit.api.Git;
import org.eclipse.jgit.api.ResetCommand;
@@ -16,17 +25,7 @@ import uk.ac.ic.wlgitbridge.util.Log;
import uk.ac.ic.wlgitbridge.util.Project;
import uk.ac.ic.wlgitbridge.util.Util;
-import java.io.File;
-import java.io.IOException;
-import java.nio.charset.StandardCharsets;
-import java.nio.file.FileVisitResult;
-import java.nio.file.FileVisitor;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.nio.file.attribute.BasicFileAttributes;
-import java.util.*;
-
-/**
+/*
* Class representing a Git repository.
*
* It stores the projectName and repo separately because the hooks need to be
@@ -40,241 +39,193 @@ import java.util.*;
*/
public class GitProjectRepo implements ProjectRepo {
- private final String projectName;
- private Optional repository;
+ private final String projectName;
+ private Optional repository;
- public static GitProjectRepo fromJGitRepo(Repository repo) {
- return new GitProjectRepo(
- repo.getWorkTree().getName(), Optional.of(repo));
+ public static GitProjectRepo fromJGitRepo(Repository repo) {
+ return new GitProjectRepo(repo.getWorkTree().getName(), Optional.of(repo));
+ }
+
+ public static GitProjectRepo fromName(String projectName) {
+ return new GitProjectRepo(projectName, Optional.empty());
+ }
+
+ GitProjectRepo(String projectName, Optional repository) {
+ Preconditions.checkArgument(Project.isValidProjectName(projectName));
+ this.projectName = projectName;
+ this.repository = repository;
+ }
+
+ @Override
+ public String getProjectName() {
+ return projectName;
+ }
+
+ @Override
+ public void initRepo(RepoStore repoStore) throws IOException {
+ initRepositoryField(repoStore);
+ Preconditions.checkState(repository.isPresent());
+ Repository repo = this.repository.get();
+ // TODO: assert that this is a fresh repo. At the moment, we can't be
+ // sure whether the repo to be init'd doesn't exist or is just fresh
+ // and we crashed / aborted while committing
+ if (repo.getObjectDatabase().exists()) return;
+ repo.create();
+ }
+
+ @Override
+ public void useExistingRepository(RepoStore repoStore) throws IOException {
+ initRepositoryField(repoStore);
+ Preconditions.checkState(repository.isPresent());
+ Preconditions.checkState(repository.get().getObjectDatabase().exists());
+ }
+
+ @Override
+ public RawDirectory getDirectory() throws IOException, GitUserException {
+ Preconditions.checkState(repository.isPresent());
+ return new RepositoryObjectTreeWalker(repository.get()).getDirectoryContents(Optional.empty());
+ }
+
+ @Override
+ public Collection commitAndGetMissing(GitDirectoryContents contents) throws IOException {
+ try {
+ return doCommitAndGetMissing(contents);
+ } catch (GitAPIException e) {
+ throw new IOException(e);
}
+ }
- public static GitProjectRepo fromName(String projectName) {
- return new GitProjectRepo(projectName, Optional.empty());
+ @Override
+ public void runGC() throws IOException {
+ Preconditions.checkState(repository.isPresent(), "Repo is not present");
+ File dir = getProjectDir();
+ Preconditions.checkState(dir.isDirectory());
+ Log.debug("[{}] Running git gc", projectName);
+ Process proc = new ProcessBuilder("git", "gc").directory(dir).start();
+ int exitCode;
+ try {
+ exitCode = proc.waitFor();
+ Log.debug("Exit: {}", exitCode);
+ } catch (InterruptedException e) {
+ throw new RuntimeException(e);
}
-
- GitProjectRepo(String projectName, Optional repository) {
- Preconditions.checkArgument(Project.isValidProjectName(projectName));
- this.projectName = projectName;
- this.repository = repository;
+ if (exitCode != 0) {
+ Log.warn("[{}] Git gc failed", dir.getAbsolutePath());
+ Log.warn(IOUtils.toString(proc.getInputStream(), StandardCharsets.UTF_8));
+ Log.warn(IOUtils.toString(proc.getErrorStream(), StandardCharsets.UTF_8));
+ throw new IOException("git gc error");
}
+ Log.debug("[{}] git gc successful", projectName);
+ }
- @Override
- public String getProjectName() {
- return projectName;
- }
+ @Override
+ public void deleteIncomingPacks() throws IOException {
+ Log.debug("[{}] Checking for garbage `incoming` files", projectName);
+ Files.walkFileTree(
+ getDotGitDir().toPath(),
+ new FileVisitor() {
+ @Override
+ public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs)
+ throws IOException {
+ return FileVisitResult.CONTINUE;
+ }
- @Override
- public void initRepo(
- RepoStore repoStore
- ) throws IOException {
- initRepositoryField(repoStore);
- Preconditions.checkState(repository.isPresent());
- Repository repo = this.repository.get();
- // TODO: assert that this is a fresh repo. At the moment, we can't be
- // sure whether the repo to be init'd doesn't exist or is just fresh
- // and we crashed / aborted while committing
- if (repo.getObjectDatabase().exists()) return;
- repo.create();
- }
-
- @Override
- public void useExistingRepository(
- RepoStore repoStore
- ) throws IOException {
- initRepositoryField(repoStore);
- Preconditions.checkState(repository.isPresent());
- Preconditions.checkState(
- repository.get().getObjectDatabase().exists()
- );
- }
-
- @Override
- public RawDirectory getDirectory()
- throws IOException, GitUserException {
- Preconditions.checkState(repository.isPresent());
- return new RepositoryObjectTreeWalker(
- repository.get()
- ).getDirectoryContents(Optional.empty());
- }
-
- @Override
- public Collection commitAndGetMissing(
- GitDirectoryContents contents
- ) throws IOException {
- try {
- return doCommitAndGetMissing(contents);
- } catch (GitAPIException e) {
- throw new IOException(e);
- }
- }
-
- @Override
- public void runGC() throws IOException {
- Preconditions.checkState(
- repository.isPresent(),
- "Repo is not present"
- );
- File dir = getProjectDir();
- Preconditions.checkState(dir.isDirectory());
- Log.debug("[{}] Running git gc", projectName);
- Process proc = new ProcessBuilder(
- "git", "gc"
- ).directory(dir).start();
- int exitCode;
- try {
- exitCode = proc.waitFor();
- Log.debug("Exit: {}", exitCode);
- } catch (InterruptedException e) {
- throw new RuntimeException(e);
- }
- if (exitCode != 0) {
- Log.warn("[{}] Git gc failed", dir.getAbsolutePath());
- Log.warn(IOUtils.toString(
- proc.getInputStream(),
- StandardCharsets.UTF_8
- ));
- Log.warn(IOUtils.toString(
- proc.getErrorStream(),
- StandardCharsets.UTF_8
- ));
- throw new IOException("git gc error");
- }
- Log.debug("[{}] git gc successful", projectName);
- }
-
- @Override
- public void deleteIncomingPacks() throws IOException {
- Log.debug(
- "[{}] Checking for garbage `incoming` files",
- projectName
- );
- Files.walkFileTree(getDotGitDir().toPath(), new FileVisitor() {
- @Override
- public FileVisitResult preVisitDirectory(
- Path dir,
- BasicFileAttributes attrs
- ) throws IOException {
- return FileVisitResult.CONTINUE;
+ @Override
+ public FileVisitResult visitFile(Path file, BasicFileAttributes attrs)
+ throws IOException {
+ File file_ = file.toFile();
+ String name = file_.getName();
+ if (name.startsWith("incoming_") && name.endsWith(".pack")) {
+ Log.debug("Deleting garbage `incoming` file: {}", file_);
+ Preconditions.checkState(file_.delete());
}
+ return FileVisitResult.CONTINUE;
+ }
- @Override
- public FileVisitResult visitFile(
- Path file,
- BasicFileAttributes attrs
- ) throws IOException {
- File file_ = file.toFile();
- String name = file_.getName();
- if (name.startsWith("incoming_") && name.endsWith(".pack")) {
- Log.debug("Deleting garbage `incoming` file: {}", file_);
- Preconditions.checkState(file_.delete());
- }
- return FileVisitResult.CONTINUE;
+ @Override
+ public FileVisitResult visitFileFailed(Path file, IOException exc) throws IOException {
+ Preconditions.checkNotNull(file);
+ Preconditions.checkNotNull(exc);
+ Log.warn("Failed to visit file: " + file, exc);
+ return FileVisitResult.TERMINATE;
+ }
+
+ @Override
+ public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException {
+ Preconditions.checkNotNull(dir);
+ if (exc != null) {
+ return FileVisitResult.TERMINATE;
}
-
- @Override
- public FileVisitResult visitFileFailed(
- Path file,
- IOException exc
- ) throws IOException {
- Preconditions.checkNotNull(file);
- Preconditions.checkNotNull(exc);
- Log.warn("Failed to visit file: " + file, exc);
- return FileVisitResult.TERMINATE;
- }
-
- @Override
- public FileVisitResult postVisitDirectory(
- Path dir,
- IOException exc
- ) throws IOException {
- Preconditions.checkNotNull(dir);
- if (exc != null) {
- return FileVisitResult.TERMINATE;
- }
- return FileVisitResult.CONTINUE;
- }
-
+ return FileVisitResult.CONTINUE;
+ }
});
- }
+ }
- @Override
- public File getProjectDir() {
- return getJGitRepository().getDirectory().getParentFile();
- }
+ @Override
+ public File getProjectDir() {
+ return getJGitRepository().getDirectory().getParentFile();
+ }
- public void resetHard() throws IOException {
- Git git = new Git(getJGitRepository());
- try {
- git.reset().setMode(ResetCommand.ResetType.HARD).call();
- } catch (GitAPIException e) {
- throw new IOException(e);
- }
+ public void resetHard() throws IOException {
+ Git git = new Git(getJGitRepository());
+ try {
+ git.reset().setMode(ResetCommand.ResetType.HARD).call();
+ } catch (GitAPIException e) {
+ throw new IOException(e);
}
+ }
- @Override
- public Repository getJGitRepository() {
- return repository.get();
+ @Override
+ public Repository getJGitRepository() {
+ return repository.get();
+ }
+
+ public File getDotGitDir() {
+ return getJGitRepository().getWorkTree();
+ }
+
+ private void initRepositoryField(RepoStore repoStore) throws IOException {
+ Preconditions.checkNotNull(repoStore);
+ Preconditions.checkArgument(Project.isValidProjectName(projectName));
+ Preconditions.checkState(!repository.isPresent());
+ repository = Optional.of(createJGitRepository(repoStore, projectName));
+ }
+
+ private Repository createJGitRepository(RepoStore repoStore, String projName) throws IOException {
+ File repoDir = new File(repoStore.getRootDirectory(), projName);
+ return new FileRepositoryBuilder().setWorkTree(repoDir).build();
+ }
+
+ private Collection doCommitAndGetMissing(GitDirectoryContents contents)
+ throws IOException, GitAPIException {
+ Preconditions.checkState(repository.isPresent());
+ Repository repo = getJGitRepository();
+ resetHard();
+ String name = getProjectName();
+ Log.debug("[{}] Writing commit", name);
+ contents.write();
+ Git git = new Git(getJGitRepository());
+ Log.debug("[{}] Getting missing files", name);
+ Set missingFiles = git.status().call().getMissing();
+ for (String missing : missingFiles) {
+ Log.debug("[{}] Git rm {}", name, missing);
+ git.rm().setCached(true).addFilepattern(missing).call();
}
-
- public File getDotGitDir() {
- return getJGitRepository().getWorkTree();
- }
-
- private void initRepositoryField(RepoStore repoStore) throws IOException {
- Preconditions.checkNotNull(repoStore);
- Preconditions.checkArgument(Project.isValidProjectName(projectName));
- Preconditions.checkState(!repository.isPresent());
- repository = Optional.of(createJGitRepository(repoStore, projectName));
- }
-
- private Repository createJGitRepository(
- RepoStore repoStore,
- String projName
- ) throws IOException {
- File repoDir = new File(repoStore.getRootDirectory(), projName);
- return new FileRepositoryBuilder().setWorkTree(repoDir).build();
- }
-
- private Collection doCommitAndGetMissing(
- GitDirectoryContents contents
- ) throws IOException, GitAPIException {
- Preconditions.checkState(repository.isPresent());
- Repository repo = getJGitRepository();
- resetHard();
- String name = getProjectName();
- Log.debug("[{}] Writing commit", name);
- contents.write();
- Git git = new Git(getJGitRepository());
- Log.debug("[{}] Getting missing files", name);
- Set missingFiles = git.status().call().getMissing();
- for (String missing : missingFiles) {
- Log.debug("[{}] Git rm {}", name, missing);
- git.rm().setCached(true).addFilepattern(missing).call();
- }
- Log.debug("[{}] Calling Git add", name);
- git.add(
- ).setWorkingTreeIterator(
- new NoGitignoreIterator(repo)
- ).addFilepattern(".").call();
- Log.debug("[{}] Calling Git commit", name);
- git.commit(
- ).setAuthor(
- new PersonIdent(
- contents.getUserName(),
- contents.getUserEmail(),
- contents.getWhen(),
- TimeZone.getDefault()
- )
- ).setMessage(
- contents.getCommitMessage()
- ).call();
- Log.debug(
- "[{}] Deleting files in directory: {}",
- name,
- contents.getDirectory().getAbsolutePath()
- );
- Util.deleteInDirectoryApartFrom(contents.getDirectory(), ".git");
- return missingFiles;
- }
-
+ Log.debug("[{}] Calling Git add", name);
+ git.add().setWorkingTreeIterator(new NoGitignoreIterator(repo)).addFilepattern(".").call();
+ Log.debug("[{}] Calling Git commit", name);
+ git.commit()
+ .setAuthor(
+ new PersonIdent(
+ contents.getUserName(),
+ contents.getUserEmail(),
+ contents.getWhen(),
+ TimeZone.getDefault()))
+ .setMessage(contents.getCommitMessage())
+ .call();
+ Log.debug(
+ "[{}] Deleting files in directory: {}", name, contents.getDirectory().getAbsolutePath());
+ Util.deleteInDirectoryApartFrom(contents.getDirectory(), ".git");
+ return missingFiles;
+ }
}
diff --git a/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/repo/NoGitignoreIterator.java b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/repo/NoGitignoreIterator.java
index 64103c075e..437fdc1747 100644
--- a/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/repo/NoGitignoreIterator.java
+++ b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/repo/NoGitignoreIterator.java
@@ -1,5 +1,7 @@
package uk.ac.ic.wlgitbridge.bridge.repo;
+import java.io.File;
+import java.lang.reflect.Field;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.treewalk.AbstractTreeIterator;
import org.eclipse.jgit.treewalk.FileTreeIterator;
@@ -7,81 +9,65 @@ import org.eclipse.jgit.treewalk.WorkingTreeIterator;
import org.eclipse.jgit.treewalk.WorkingTreeOptions;
import org.eclipse.jgit.util.FS;
-import java.io.File;
-import java.lang.reflect.Field;
-
-/**
+/*
* Created by winston on 08/10/2016.
*/
public class NoGitignoreIterator extends FileTreeIterator {
- private static final Field ignoreNodeField;
+ private static final Field ignoreNodeField;
- static {
- try {
- ignoreNodeField = WorkingTreeIterator.class.getDeclaredField(
- "ignoreNode"
- );
- } catch (NoSuchFieldException e) {
- throw new RuntimeException(e);
- }
- ignoreNodeField.setAccessible(true);
+ static {
+ try {
+ ignoreNodeField = WorkingTreeIterator.class.getDeclaredField("ignoreNode");
+ } catch (NoSuchFieldException e) {
+ throw new RuntimeException(e);
}
+ ignoreNodeField.setAccessible(true);
+ }
- public NoGitignoreIterator(Repository repo) {
- super(repo);
- }
+ public NoGitignoreIterator(Repository repo) {
+ super(repo);
+ }
- public NoGitignoreIterator(
- Repository repo,
- FileModeStrategy fileModeStrategy
- ) {
- super(repo, fileModeStrategy);
- }
+ public NoGitignoreIterator(Repository repo, FileModeStrategy fileModeStrategy) {
+ super(repo, fileModeStrategy);
+ }
- public NoGitignoreIterator(File root, FS fs, WorkingTreeOptions options) {
- super(root, fs, options);
- }
+ public NoGitignoreIterator(File root, FS fs, WorkingTreeOptions options) {
+ super(root, fs, options);
+ }
- public NoGitignoreIterator(
- File root,
- FS fs,
- WorkingTreeOptions options,
- FileModeStrategy fileModeStrategy
- ) {
- super(root, fs, options, fileModeStrategy);
- }
+ public NoGitignoreIterator(
+ File root, FS fs, WorkingTreeOptions options, FileModeStrategy fileModeStrategy) {
+ super(root, fs, options, fileModeStrategy);
+ }
- protected NoGitignoreIterator(FileTreeIterator p, File root, FS fs) {
- super(p, root, fs);
- }
+ protected NoGitignoreIterator(FileTreeIterator p, File root, FS fs) {
+ super(p, root, fs);
+ }
- protected NoGitignoreIterator(
- WorkingTreeIterator p,
- File root,
- FS fs,
- FileModeStrategy fileModeStrategy
- ) {
- super(p, root, fs, fileModeStrategy);
- }
+ protected NoGitignoreIterator(
+ WorkingTreeIterator p, File root, FS fs, FileModeStrategy fileModeStrategy) {
+ super(p, root, fs, fileModeStrategy);
+ }
- // Note: the `list` is a list of top-level entities in this directory,
- // not a full list of files in the tree.
- @Override
- protected void init(Entry[] list) {
- super.init(list);
- try {
- ignoreNodeField.set(this, null);
- } catch (IllegalAccessException e) {
- throw new RuntimeException(e);
- }
+ // Note: the `list` is a list of top-level entities in this directory,
+ // not a full list of files in the tree.
+ @Override
+ protected void init(Entry[] list) {
+ super.init(list);
+ try {
+ ignoreNodeField.set(this, null);
+ } catch (IllegalAccessException e) {
+ throw new RuntimeException(e);
}
+ }
- // When entering a sub-directory, create a new instance of this class,
- // so we can also ignore gitignore specifications in sub-directories
- @Override
- protected AbstractTreeIterator enterSubtree() {
- String fullPath = getDirectory().getAbsolutePath() + "/" + current().getName();
- return new NoGitignoreIterator(this, new File(fullPath), fs, fileModeStrategy);
- }
+ // When entering a sub-directory, create a new instance of this class,
+ // so we can also ignore gitignore specifications in sub-directories
+ @Override
+ protected AbstractTreeIterator enterSubtree() {
+ String fullPath = getDirectory().getAbsolutePath() + "/" + current().getName();
+ return new NoGitignoreIterator(this, new File(fullPath), fs, fileModeStrategy);
+ }
}
diff --git a/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/repo/ProjectRepo.java b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/repo/ProjectRepo.java
index 1e77d45010..5d82e3dd83 100644
--- a/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/repo/ProjectRepo.java
+++ b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/repo/ProjectRepo.java
@@ -1,41 +1,34 @@
package uk.ac.ic.wlgitbridge.bridge.repo;
+import java.io.File;
+import java.io.IOException;
+import java.util.Collection;
import org.eclipse.jgit.lib.Repository;
import uk.ac.ic.wlgitbridge.data.filestore.GitDirectoryContents;
import uk.ac.ic.wlgitbridge.data.filestore.RawDirectory;
import uk.ac.ic.wlgitbridge.git.exception.GitUserException;
-import java.io.File;
-import java.io.IOException;
-import java.util.Collection;
-
-/**
+/*
* Created by winston on 20/08/2016.
*/
public interface ProjectRepo {
- String getProjectName();
+ String getProjectName();
- void initRepo(
- RepoStore repoStore
- ) throws IOException;
+ void initRepo(RepoStore repoStore) throws IOException;
- void useExistingRepository(
- RepoStore repoStore
- ) throws IOException;
+ void useExistingRepository(RepoStore repoStore) throws IOException;
- RawDirectory getDirectory(
- ) throws IOException, GitUserException;
+ RawDirectory getDirectory() throws IOException, GitUserException;
- Collection commitAndGetMissing(
- GitDirectoryContents gitDirectoryContents
- ) throws IOException, GitUserException;
+ Collection commitAndGetMissing(GitDirectoryContents gitDirectoryContents)
+ throws IOException, GitUserException;
- void runGC() throws IOException;
+ void runGC() throws IOException;
- void deleteIncomingPacks() throws IOException;
+ void deleteIncomingPacks() throws IOException;
- File getProjectDir();
+ File getProjectDir();
- Repository getJGitRepository();
+ Repository getJGitRepository();
}
diff --git a/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/repo/RepoStore.java b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/repo/RepoStore.java
index 23bd294693..63ee3d1462 100644
--- a/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/repo/RepoStore.java
+++ b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/repo/RepoStore.java
@@ -1,102 +1,82 @@
package uk.ac.ic.wlgitbridge.bridge.repo;
-import org.eclipse.jgit.lib.ObjectId;
-import org.eclipse.jgit.lib.Repository;
-
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.Collection;
+import org.eclipse.jgit.lib.ObjectId;
+import org.eclipse.jgit.lib.Repository;
-/**
+/*
* Created by winston on 20/08/2016.
*/
public interface RepoStore {
- /* Still need to get rid of these two methods.
- Main dependency: GitRepoStore needs a Repository which needs a directory.
- Instead, use a visitor or something. */
- String getRepoStorePath();
+ /* Still need to get rid of these two methods.
+ Main dependency: GitRepoStore needs a Repository which needs a directory.
+ Instead, use a visitor or something. */
+ String getRepoStorePath();
- File getRootDirectory();
+ File getRootDirectory();
- ProjectRepo initRepo(String project) throws IOException;
+ ProjectRepo initRepo(String project) throws IOException;
- ProjectRepo getExistingRepo(String project) throws IOException;
+ ProjectRepo getExistingRepo(String project) throws IOException;
- ProjectRepo useJGitRepo(Repository repo, ObjectId commitId);
+ ProjectRepo useJGitRepo(Repository repo, ObjectId commitId);
- void purgeNonexistentProjects(
- Collection existingProjectNames
- );
+ void purgeNonexistentProjects(Collection existingProjectNames);
- long totalSize();
+ long totalSize();
- /**
- * Tars and bzip2s the .git directory of the given project. Throws an
- * IOException if the project doesn't exist. The returned stream is a copy
- * of the original .git directory, which must be deleted using remove().
- */
- InputStream bzip2Project(
- String projectName,
- long[] sizePtr
- ) throws IOException;
+ /*
+ * Tars and bzip2s the .git directory of the given project. Throws an
+ * IOException if the project doesn't exist. The returned stream is a copy
+ * of the original .git directory, which must be deleted using remove().
+ */
+ InputStream bzip2Project(String projectName, long[] sizePtr) throws IOException;
- default InputStream bzip2Project(
- String projectName
- ) throws IOException {
- return bzip2Project(projectName, null);
- }
+ default InputStream bzip2Project(String projectName) throws IOException {
+ return bzip2Project(projectName, null);
+ }
- /**
- * Tars and gzips the .git directory of the given project. Throws an
- * IOException if the project doesn't exist. The returned stream is a copy
- * of the original .git directory, which must be deleted using remove().
- */
- InputStream gzipProject(
- String projectName,
- long[] sizePtr
- ) throws IOException;
+ /*
+ * Tars and gzips the .git directory of the given project. Throws an
+ * IOException if the project doesn't exist. The returned stream is a copy
+ * of the original .git directory, which must be deleted using remove().
+ */
+ InputStream gzipProject(String projectName, long[] sizePtr) throws IOException;
- default InputStream gzipProject(
- String projectName
- ) throws IOException {
- return gzipProject(projectName, null);
- }
+ default InputStream gzipProject(String projectName) throws IOException {
+ return gzipProject(projectName, null);
+ }
- void gcProject(String projectName) throws IOException;
+ void gcProject(String projectName) throws IOException;
- /**
- * Called after {@link #bzip2Project(String, long[])}'s has been safely
- * uploaded to the swap store. Removes all traces of the project from disk,
- * i.e. not just its .git, but the whole project's git directory.
- * @param projectName
- * @throws IOException
- */
- void remove(String projectName) throws IOException;
+ /*
+ * Called after {@link #bzip2Project(String, long[])}'s has been safely
+ * uploaded to the swap store. Removes all traces of the project from disk,
+ * i.e. not just its .git, but the whole project's git directory.
+ * @param projectName
+ * @throws IOException
+ */
+ void remove(String projectName) throws IOException;
- /**
- * Unbzip2s the given data stream into a .git directory for projectName.
- * Creates the project's git directory.
- * If projectName already exists, throws an IOException.
- * @param projectName the name of the project, e.g. abc123
- * @param dataStream the data stream containing the bzipped contents.
- */
- void unbzip2Project(
- String projectName,
- InputStream dataStream
- ) throws IOException;
-
- /**
- * Ungzips the given data stream into a .git directory for projectName.
- * Creates the project's git directory.
- * If projectName already exists, throws an IOException.
- * @param projectName the name of the project, e.g. abc123
- * @param dataStream the data stream containing the gzip contents.
- */
- void ungzipProject(
- String projectName,
- InputStream dataStream
- ) throws IOException;
+ /*
+ * Unbzip2s the given data stream into a .git directory for projectName.
+ * Creates the project's git directory.
+ * If projectName already exists, throws an IOException.
+ * @param projectName the name of the project, e.g. abc123
+ * @param dataStream the data stream containing the bzipped contents.
+ */
+ void unbzip2Project(String projectName, InputStream dataStream) throws IOException;
+ /*
+ * Ungzips the given data stream into a .git directory for projectName.
+ * Creates the project's git directory.
+ * If projectName already exists, throws an IOException.
+ * @param projectName the name of the project, e.g. abc123
+ * @param dataStream the data stream containing the gzip contents.
+ */
+ void ungzipProject(String projectName, InputStream dataStream) throws IOException;
}
diff --git a/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/repo/RepoStoreConfig.java b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/repo/RepoStoreConfig.java
index 52d41104a1..feb01d3ded 100644
--- a/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/repo/RepoStoreConfig.java
+++ b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/repo/RepoStoreConfig.java
@@ -1,29 +1,27 @@
package uk.ac.ic.wlgitbridge.bridge.repo;
-import javax.annotation.Nullable;
import java.util.Optional;
+import javax.annotation.Nullable;
-/**
+/*
* Created by winston on 02/07/2017.
*/
public class RepoStoreConfig {
- @Nullable
- private final Long maxFileSize;
+ @Nullable private final Long maxFileSize;
- @Nullable
- private final Long maxFileNum;
+ @Nullable private final Long maxFileNum;
- public RepoStoreConfig(Long maxFileSize, Long maxFileNum) {
- this.maxFileSize = maxFileSize;
- this.maxFileNum = maxFileNum;
- }
+ public RepoStoreConfig(Long maxFileSize, Long maxFileNum) {
+ this.maxFileSize = maxFileSize;
+ this.maxFileNum = maxFileNum;
+ }
- public Optional getMaxFileSize() {
- return Optional.ofNullable(maxFileSize);
- }
+ public Optional getMaxFileSize() {
+ return Optional.ofNullable(maxFileSize);
+ }
- public Optional getMaxFileNum() {
- return Optional.ofNullable(maxFileNum);
- }
+ public Optional getMaxFileNum() {
+ return Optional.ofNullable(maxFileNum);
+ }
}
diff --git a/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/repo/WalkOverrideGitRepo.java b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/repo/WalkOverrideGitRepo.java
index c240001c7c..ded4269ff3 100644
--- a/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/repo/WalkOverrideGitRepo.java
+++ b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/repo/WalkOverrideGitRepo.java
@@ -1,5 +1,9 @@
package uk.ac.ic.wlgitbridge.bridge.repo;
+import java.io.File;
+import java.io.IOException;
+import java.util.Collection;
+import java.util.Optional;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.Repository;
import uk.ac.ic.wlgitbridge.data.filestore.GitDirectoryContents;
@@ -7,12 +11,7 @@ import uk.ac.ic.wlgitbridge.data.filestore.RawDirectory;
import uk.ac.ic.wlgitbridge.git.exception.GitUserException;
import uk.ac.ic.wlgitbridge.git.util.RepositoryObjectTreeWalker;
-import java.io.File;
-import java.io.IOException;
-import java.util.Collection;
-import java.util.Optional;
-
-/**
+/*
* This class takes a GitProjectRepo and delegates all calls to it.
*
* The purpose is to insert a file size check in {@link #getDirectory()}.
@@ -22,74 +21,69 @@ import java.util.Optional;
*/
public class WalkOverrideGitRepo implements ProjectRepo {
- private final GitProjectRepo gitRepo;
+ private final GitProjectRepo gitRepo;
- private final Optional maxFileSize;
+ private final Optional maxFileSize;
- private final Optional commitId;
+ private final Optional commitId;
- public WalkOverrideGitRepo(
- GitProjectRepo gitRepo,
- Optional maxFileSize,
- Optional commitId
- ) {
- this.gitRepo = gitRepo;
- this.maxFileSize = maxFileSize;
- this.commitId = commitId;
+ public WalkOverrideGitRepo(
+ GitProjectRepo gitRepo, Optional maxFileSize, Optional commitId) {
+ this.gitRepo = gitRepo;
+ this.maxFileSize = maxFileSize;
+ this.commitId = commitId;
+ }
+
+ @Override
+ public String getProjectName() {
+ return gitRepo.getProjectName();
+ }
+
+ @Override
+ public void initRepo(RepoStore repoStore) throws IOException {
+ gitRepo.initRepo(repoStore);
+ }
+
+ @Override
+ public void useExistingRepository(RepoStore repoStore) throws IOException {
+ gitRepo.useExistingRepository(repoStore);
+ }
+
+ @Override
+ public RawDirectory getDirectory() throws IOException, GitUserException {
+ Repository repo = gitRepo.getJGitRepository();
+ RepositoryObjectTreeWalker walker;
+ if (commitId.isPresent()) {
+ walker = new RepositoryObjectTreeWalker(repo, commitId.get());
+ } else {
+ walker = new RepositoryObjectTreeWalker(repo);
}
+ return walker.getDirectoryContents(maxFileSize);
+ }
- @Override
- public String getProjectName() {
- return gitRepo.getProjectName();
- }
+ @Override
+ public Collection commitAndGetMissing(GitDirectoryContents gitDirectoryContents)
+ throws GitUserException, IOException {
+ return gitRepo.commitAndGetMissing(gitDirectoryContents);
+ }
- @Override
- public void initRepo(RepoStore repoStore) throws IOException {
- gitRepo.initRepo(repoStore);
- }
+ @Override
+ public void runGC() throws IOException {
+ gitRepo.runGC();
+ }
- @Override
- public void useExistingRepository(RepoStore repoStore) throws IOException {
- gitRepo.useExistingRepository(repoStore);
- }
+ @Override
+ public void deleteIncomingPacks() throws IOException {
+ gitRepo.deleteIncomingPacks();
+ }
- @Override
- public RawDirectory getDirectory() throws IOException, GitUserException {
- Repository repo = gitRepo.getJGitRepository();
- RepositoryObjectTreeWalker walker;
- if (commitId.isPresent()) {
- walker = new RepositoryObjectTreeWalker(repo, commitId.get());
- } else {
- walker = new RepositoryObjectTreeWalker(repo);
- }
- return walker.getDirectoryContents(maxFileSize);
- }
-
- @Override
- public Collection commitAndGetMissing(
- GitDirectoryContents gitDirectoryContents
- ) throws GitUserException, IOException {
- return gitRepo.commitAndGetMissing(gitDirectoryContents);
- }
-
- @Override
- public void runGC() throws IOException {
- gitRepo.runGC();
- }
-
- @Override
- public void deleteIncomingPacks() throws IOException {
- gitRepo.deleteIncomingPacks();
- }
-
- @Override
- public File getProjectDir() {
- return gitRepo.getProjectDir();
- }
-
- @Override
- public Repository getJGitRepository() {
- return gitRepo.getJGitRepository();
- }
+ @Override
+ public File getProjectDir() {
+ return gitRepo.getProjectDir();
+ }
+ @Override
+ public Repository getJGitRepository() {
+ return gitRepo.getJGitRepository();
+ }
}
diff --git a/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/resource/ResourceCache.java b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/resource/ResourceCache.java
index 7a520bb3f8..3bf568f74c 100644
--- a/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/resource/ResourceCache.java
+++ b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/resource/ResourceCache.java
@@ -1,24 +1,22 @@
package uk.ac.ic.wlgitbridge.bridge.resource;
-import uk.ac.ic.wlgitbridge.data.filestore.RawFile;
-import uk.ac.ic.wlgitbridge.git.exception.SizeLimitExceededException;
-
import java.io.IOException;
import java.util.Map;
import java.util.Optional;
+import uk.ac.ic.wlgitbridge.data.filestore.RawFile;
+import uk.ac.ic.wlgitbridge.git.exception.SizeLimitExceededException;
-/**
+/*
* Created by winston on 20/08/2016.
*/
public interface ResourceCache {
- RawFile get(
- String projectName,
- String url,
- String newPath,
- Map fileTable,
- Map fetchedUrls,
- Optional maxFileSize
- ) throws IOException, SizeLimitExceededException;
-
+ RawFile get(
+ String projectName,
+ String url,
+ String newPath,
+ Map fileTable,
+ Map fetchedUrls,
+ Optional maxFileSize)
+ throws IOException, SizeLimitExceededException;
}
diff --git a/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/resource/UrlResourceCache.java b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/resource/UrlResourceCache.java
index 29d218d3f9..d01027d2a2 100644
--- a/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/resource/UrlResourceCache.java
+++ b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/resource/UrlResourceCache.java
@@ -1,6 +1,12 @@
package uk.ac.ic.wlgitbridge.bridge.resource;
import static org.asynchttpclient.Dsl.*;
+
+import java.io.IOException;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+import java.util.concurrent.ExecutionException;
import uk.ac.ic.wlgitbridge.bridge.db.DBStore;
import uk.ac.ic.wlgitbridge.data.filestore.RawFile;
import uk.ac.ic.wlgitbridge.data.filestore.RepositoryFile;
@@ -10,133 +16,124 @@ import uk.ac.ic.wlgitbridge.io.http.ning.NingHttpClientFacade;
import uk.ac.ic.wlgitbridge.snapshot.exception.FailedConnectionException;
import uk.ac.ic.wlgitbridge.util.Log;
-import java.io.IOException;
-import java.util.List;
-import java.util.Map;
-import java.util.Optional;
-import java.util.concurrent.ExecutionException;
-
-/**
+/*
* Created by winston on 20/08/2016.
*/
public class UrlResourceCache implements ResourceCache {
- private final DBStore dbStore;
+ private final DBStore dbStore;
- private final NingHttpClientFacade http;
+ private final NingHttpClientFacade http;
- UrlResourceCache(DBStore dbStore, NingHttpClientFacade http) {
- this.dbStore = dbStore;
- this.http = http;
- }
+ UrlResourceCache(DBStore dbStore, NingHttpClientFacade http) {
+ this.dbStore = dbStore;
+ this.http = http;
+ }
- public UrlResourceCache(DBStore dbStore) {
- this(dbStore, new NingHttpClient(asyncHttpClient()));
- }
+ public UrlResourceCache(DBStore dbStore) {
+ this(dbStore, new NingHttpClient(asyncHttpClient()));
+ }
- @Override
- public RawFile get(
- String projectName,
- String url,
- String newPath,
- Map fileTable,
- Map fetchedUrls,
- Optional maxFileSize
- ) throws IOException, SizeLimitExceededException {
- String path = dbStore.getPathForURLInProject(projectName, getCacheKeyFromUrl(url));
- byte[] contents;
- if (path == null) {
- path = newPath;
- contents = fetch(projectName, url, path, maxFileSize);
- fetchedUrls.put(url, contents);
+ @Override
+ public RawFile get(
+ String projectName,
+ String url,
+ String newPath,
+ Map fileTable,
+ Map fetchedUrls,
+ Optional maxFileSize)
+ throws IOException, SizeLimitExceededException {
+ String path = dbStore.getPathForURLInProject(projectName, getCacheKeyFromUrl(url));
+ byte[] contents;
+ if (path == null) {
+ path = newPath;
+ contents = fetch(projectName, url, path, maxFileSize);
+ fetchedUrls.put(url, contents);
+ } else {
+ Log.debug("Found (" + projectName + "): " + url);
+ Log.debug("At (" + projectName + "): " + path);
+ contents = fetchedUrls.get(url);
+ if (contents == null) {
+ RawFile rawFile = fileTable.get(path);
+ if (rawFile == null) {
+ Log.warn(
+ "File "
+ + path
+ + " was not in the current commit, "
+ + "or the git tree, yet path was not null. "
+ + "File url is: "
+ + url);
+ contents = fetch(projectName, url, path, maxFileSize);
} else {
- Log.debug("Found (" + projectName + "): " + url);
- Log.debug("At (" + projectName + "): " + path);
- contents = fetchedUrls.get(url);
- if (contents == null) {
- RawFile rawFile = fileTable.get(path);
- if (rawFile == null) {
- Log.warn(
- "File " + path
- + " was not in the current commit, "
- + "or the git tree, yet path was not null. "
- + "File url is: "
- + url
- );
- contents = fetch(projectName, url, path, maxFileSize);
- } else {
- contents = rawFile.getContents();
- }
- }
+ contents = rawFile.getContents();
}
- return new RepositoryFile(newPath, contents);
+ }
}
+ return new RepositoryFile(newPath, contents);
+ }
- private byte[] fetch(
- String projectName,
- final String url,
- String path,
- Optional maxFileSize
- ) throws FailedConnectionException, SizeLimitExceededException {
- byte[] contents;
- Log.debug("GET -> " + url);
- try {
- contents = http.get(url, hs -> {
+ private byte[] fetch(
+ String projectName, final String url, String path, Optional maxFileSize)
+ throws FailedConnectionException, SizeLimitExceededException {
+ byte[] contents;
+ Log.debug("GET -> " + url);
+ try {
+ contents =
+ http.get(
+ url,
+ hs -> {
List contentLengths = hs.getAll("Content-Length");
if (!maxFileSize.isPresent()) {
- return true;
+ return true;
}
if (contentLengths.isEmpty()) {
- return true;
+ return true;
}
long contentLength = Long.parseLong(contentLengths.get(0));
long maxFileSize_ = maxFileSize.get();
if (contentLength <= maxFileSize_) {
- return true;
+ return true;
}
throw new SizeLimitExceededException(
- Optional.of(path), contentLength, maxFileSize_
- );
- });
- } catch (ExecutionException e) {
- Throwable cause = e.getCause();
- if (cause instanceof SizeLimitExceededException) {
- throw (SizeLimitExceededException) cause;
- }
- Log.warn(
- "ExecutionException when fetching project: " +
- projectName +
- ", url: " +
- url +
- ", path: " +
- path,
- e
- );
- throw new FailedConnectionException();
- }
- if (maxFileSize.isPresent() && contents.length > maxFileSize.get()) {
- throw new SizeLimitExceededException(
- Optional.of(path), contents.length, maxFileSize.get());
- }
- dbStore.addURLIndexForProject(projectName, getCacheKeyFromUrl(url), path);
- return contents;
+ Optional.of(path), contentLength, maxFileSize_);
+ });
+ } catch (ExecutionException e) {
+ Throwable cause = e.getCause();
+ if (cause instanceof SizeLimitExceededException) {
+ throw (SizeLimitExceededException) cause;
+ }
+ Log.warn(
+ "ExecutionException when fetching project: "
+ + projectName
+ + ", url: "
+ + url
+ + ", path: "
+ + path,
+ e);
+ throw new FailedConnectionException();
}
+ if (maxFileSize.isPresent() && contents.length > maxFileSize.get()) {
+ throw new SizeLimitExceededException(Optional.of(path), contents.length, maxFileSize.get());
+ }
+ dbStore.addURLIndexForProject(projectName, getCacheKeyFromUrl(url), path);
+ return contents;
+ }
- /**
- * Construct a suitable cache key from the given file URL.
- *
- * The file URL returned by the web service may contain a token parameter
- * used for authentication. This token changes for every request, so we
- * need to strip it from the query string before using the URL as a cache
- * key.
- */
- private String getCacheKeyFromUrl(String url) {
- // We're not doing proper URL parsing here, but it should be enough to
- // remove the token without touching the important parts of the URL.
- //
- // The URL looks like:
- //
- // https://history.overleaf.com/api/projects/:project_id/blobs/:hash?token=:token&_path=:path
- return url.replaceAll("token=[^&]*", "token=REMOVED");
- }
+ /*
+ * Construct a suitable cache key from the given file URL.
+ *
+ * The file URL returned by the web service may contain a token parameter
+ * used for authentication. This token changes for every request, so we
+ * need to strip it from the query string before using the URL as a cache
+ * key.
+ */
+ private String getCacheKeyFromUrl(String url) {
+ // We're not doing proper URL parsing here, but it should be enough to
+ // remove the token without touching the important parts of the URL.
+ //
+ // The URL looks like:
+ //
+ // https://history.overleaf.com/api/projects/:project_id/blobs/:hash?token=:token&_path=:path
+ return url.replaceAll("token=[^&]*", "token=REMOVED");
+ }
}
diff --git a/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/snapshot/NetSnapshotApi.java b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/snapshot/NetSnapshotApi.java
index c289e44c30..b8f2636662 100644
--- a/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/snapshot/NetSnapshotApi.java
+++ b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/snapshot/NetSnapshotApi.java
@@ -1,6 +1,8 @@
package uk.ac.ic.wlgitbridge.bridge.snapshot;
import com.google.api.client.auth.oauth2.Credential;
+import java.util.Optional;
+import java.util.concurrent.CompletableFuture;
import uk.ac.ic.wlgitbridge.data.CandidateSnapshot;
import uk.ac.ic.wlgitbridge.snapshot.getdoc.GetDocRequest;
import uk.ac.ic.wlgitbridge.snapshot.getdoc.GetDocResult;
@@ -11,45 +13,35 @@ import uk.ac.ic.wlgitbridge.snapshot.getsavedvers.GetSavedVersResult;
import uk.ac.ic.wlgitbridge.snapshot.push.PushRequest;
import uk.ac.ic.wlgitbridge.snapshot.push.PushResult;
-import java.util.Optional;
-import java.util.concurrent.CompletableFuture;
-
-/**
+/*
* Created by winston on 20/08/2016.
*/
public class NetSnapshotApi implements SnapshotApi {
- @Override
- public CompletableFuture getDoc(
- Optional oauth2, String projectName) {
- return new GetDocRequest(opt(oauth2), projectName).request();
- }
+ @Override
+ public CompletableFuture getDoc(Optional oauth2, String projectName) {
+ return new GetDocRequest(opt(oauth2), projectName).request();
+ }
- @Override
- public CompletableFuture getForVersion(
- Optional oauth2, String projectName, int versionId) {
- return new GetForVersionRequest(
- opt(oauth2), projectName, versionId).request();
- }
+ @Override
+ public CompletableFuture getForVersion(
+ Optional oauth2, String projectName, int versionId) {
+ return new GetForVersionRequest(opt(oauth2), projectName, versionId).request();
+ }
- @Override
- public CompletableFuture getSavedVers(
- Optional oauth2, String projectName) {
- return new GetSavedVersRequest(opt(oauth2), projectName).request();
- }
+ @Override
+ public CompletableFuture getSavedVers(
+ Optional oauth2, String projectName) {
+ return new GetSavedVersRequest(opt(oauth2), projectName).request();
+ }
- @Override
- public CompletableFuture push(
- Optional oauth2,
- CandidateSnapshot candidateSnapshot,
- String postbackKey
- ) {
- return new PushRequest(
- opt(oauth2), candidateSnapshot, postbackKey).request();
- }
-
- private static Credential opt(Optional oauth2) {
- return oauth2.orElse(null);
- }
+ @Override
+ public CompletableFuture push(
+ Optional oauth2, CandidateSnapshot candidateSnapshot, String postbackKey) {
+ return new PushRequest(opt(oauth2), candidateSnapshot, postbackKey).request();
+ }
+ private static Credential opt(Optional oauth2) {
+ return oauth2.orElse(null);
+ }
}
diff --git a/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/snapshot/SnapshotApi.java b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/snapshot/SnapshotApi.java
index 0358db7834..67fec434d4 100644
--- a/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/snapshot/SnapshotApi.java
+++ b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/snapshot/SnapshotApi.java
@@ -1,54 +1,49 @@
package uk.ac.ic.wlgitbridge.bridge.snapshot;
import com.google.api.client.auth.oauth2.Credential;
+import java.util.Optional;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.CompletionException;
import uk.ac.ic.wlgitbridge.data.CandidateSnapshot;
-import uk.ac.ic.wlgitbridge.snapshot.base.MissingRepositoryException;
import uk.ac.ic.wlgitbridge.snapshot.base.ForbiddenException;
+import uk.ac.ic.wlgitbridge.snapshot.base.MissingRepositoryException;
import uk.ac.ic.wlgitbridge.snapshot.exception.FailedConnectionException;
import uk.ac.ic.wlgitbridge.snapshot.getdoc.GetDocResult;
import uk.ac.ic.wlgitbridge.snapshot.getforversion.GetForVersionResult;
import uk.ac.ic.wlgitbridge.snapshot.getsavedvers.GetSavedVersResult;
import uk.ac.ic.wlgitbridge.snapshot.push.PushResult;
-import java.util.Optional;
-import java.util.concurrent.CompletableFuture;
-import java.util.concurrent.CompletionException;
-
-/**
+/*
* Created by winston on 20/08/2016.
*/
public interface SnapshotApi {
- CompletableFuture getDoc(
- Optional oauth2, String projectName);
+ CompletableFuture getDoc(Optional oauth2, String projectName);
- CompletableFuture getForVersion(
- Optional oauth2, String projectName, int versionId);
+ CompletableFuture getForVersion(
+ Optional oauth2, String projectName, int versionId);
- CompletableFuture getSavedVers(
- Optional oauth2, String projectName);
+ CompletableFuture getSavedVers(
+ Optional oauth2, String projectName);
- CompletableFuture push(
- Optional oauth2,
- CandidateSnapshot candidateSnapshot,
- String postbackKey);
+ CompletableFuture push(
+ Optional oauth2, CandidateSnapshot candidateSnapshot, String postbackKey);
- static T getResult(CompletableFuture result)
- throws MissingRepositoryException, FailedConnectionException, ForbiddenException {
- try {
- return result.join();
- } catch (CompletionException e) {
- try {
- throw e.getCause();
- } catch (MissingRepositoryException
- | FailedConnectionException
- | ForbiddenException
- | RuntimeException r) {
- throw r;
- } catch (Throwable __) {
- throw e;
- }
- }
+ static T getResult(CompletableFuture result)
+ throws MissingRepositoryException, FailedConnectionException, ForbiddenException {
+ try {
+ return result.join();
+ } catch (CompletionException e) {
+ try {
+ throw e.getCause();
+ } catch (MissingRepositoryException
+ | FailedConnectionException
+ | ForbiddenException
+ | RuntimeException r) {
+ throw r;
+ } catch (Throwable __) {
+ throw e;
+ }
}
-
+ }
}
diff --git a/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/snapshot/SnapshotApiFacade.java b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/snapshot/SnapshotApiFacade.java
index 9aa3165e06..07ac0a9a40 100644
--- a/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/snapshot/SnapshotApiFacade.java
+++ b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/snapshot/SnapshotApiFacade.java
@@ -1,11 +1,14 @@
package uk.ac.ic.wlgitbridge.bridge.snapshot;
import com.google.api.client.auth.oauth2.Credential;
+import java.util.*;
+import java.util.concurrent.CompletableFuture;
+import java.util.stream.Collectors;
import uk.ac.ic.wlgitbridge.data.CandidateSnapshot;
import uk.ac.ic.wlgitbridge.data.model.Snapshot;
import uk.ac.ic.wlgitbridge.git.exception.GitUserException;
-import uk.ac.ic.wlgitbridge.snapshot.base.MissingRepositoryException;
import uk.ac.ic.wlgitbridge.snapshot.base.ForbiddenException;
+import uk.ac.ic.wlgitbridge.snapshot.base.MissingRepositoryException;
import uk.ac.ic.wlgitbridge.snapshot.exception.FailedConnectionException;
import uk.ac.ic.wlgitbridge.snapshot.getdoc.GetDocResult;
import uk.ac.ic.wlgitbridge.snapshot.getforversion.GetForVersionResult;
@@ -15,148 +18,104 @@ import uk.ac.ic.wlgitbridge.snapshot.getsavedvers.SnapshotInfo;
import uk.ac.ic.wlgitbridge.snapshot.push.PushResult;
import uk.ac.ic.wlgitbridge.snapshot.push.exception.InvalidProjectException;
-import java.util.*;
-import java.util.concurrent.CompletableFuture;
-import java.util.stream.Collectors;
-
-/**
+/*
* Created by winston on 02/07/2017.
*/
public class SnapshotApiFacade {
- private final SnapshotApi api;
+ private final SnapshotApi api;
- public SnapshotApiFacade(SnapshotApi api) {
- this.api = api;
+ public SnapshotApiFacade(SnapshotApi api) {
+ this.api = api;
+ }
+
+ public boolean projectExists(Optional oauth2, String projectName)
+ throws FailedConnectionException, GitUserException {
+ try {
+ SnapshotApi.getResult(api.getDoc(oauth2, projectName)).getVersionID();
+ return true;
+ } catch (InvalidProjectException e) {
+ return false;
}
+ }
- public boolean projectExists(
- Optional oauth2,
- String projectName
- ) throws FailedConnectionException, GitUserException {
- try {
- SnapshotApi
- .getResult(api.getDoc(oauth2, projectName))
- .getVersionID();
- return true;
- } catch (InvalidProjectException e) {
- return false;
+ public Optional getDoc(Optional oauth2, String projectName)
+ throws FailedConnectionException, GitUserException {
+ try {
+ GetDocResult doc = SnapshotApi.getResult(api.getDoc(oauth2, projectName));
+ doc.getVersionID();
+ return Optional.of(doc);
+ } catch (InvalidProjectException e) {
+ return Optional.empty();
+ }
+ }
+
+ public Deque getSnapshots(
+ Optional oauth2, String projectName, int afterVersionId)
+ throws GitUserException, FailedConnectionException {
+ List snapshotInfos =
+ getSnapshotInfosAfterVersion(oauth2, projectName, afterVersionId);
+ List snapshotDatas = getMatchingSnapshotData(oauth2, projectName, snapshotInfos);
+ return combine(snapshotInfos, snapshotDatas);
+ }
+
+ public PushResult push(
+ Optional oauth2, CandidateSnapshot candidateSnapshot, String postbackKey)
+ throws MissingRepositoryException, FailedConnectionException, ForbiddenException {
+ return SnapshotApi.getResult(api.push(oauth2, candidateSnapshot, postbackKey));
+ }
+
+ private List getSnapshotInfosAfterVersion(
+ Optional oauth2, String projectName, int version)
+ throws FailedConnectionException, GitUserException {
+ SortedSet versions = new TreeSet<>();
+ CompletableFuture getDoc = api.getDoc(oauth2, projectName);
+ CompletableFuture savedVers = api.getSavedVers(oauth2, projectName);
+ GetDocResult latestDoc = SnapshotApi.getResult(getDoc);
+ int latest = latestDoc.getVersionID();
+ // Handle edge-case for projects with no changes, that were imported
+ // to v2. In which case both `latest` and `version` will be zero.
+ // See: https://github.com/overleaf/writelatex-git-bridge/pull/50
+ if (latest > version || (latest == 0 && version == 0)) {
+ for (SnapshotInfo snapshotInfo : SnapshotApi.getResult(savedVers).getSavedVers()) {
+ if (snapshotInfo.getVersionId() > version) {
+ versions.add(snapshotInfo);
}
+ }
+ versions.add(
+ new SnapshotInfo(
+ latest, latestDoc.getCreatedAt(), latestDoc.getName(), latestDoc.getEmail()));
}
+ return new ArrayList<>(versions);
+ }
- public Optional getDoc(
- Optional oauth2,
- String projectName
- ) throws FailedConnectionException, GitUserException {
- try {
- GetDocResult doc = SnapshotApi
- .getResult(api.getDoc(oauth2, projectName));
- doc.getVersionID();
- return Optional.of(doc);
- } catch (InvalidProjectException e) {
- return Optional.empty();
- }
+ private List getMatchingSnapshotData(
+ Optional oauth2, String projectName, List snapshotInfos)
+ throws FailedConnectionException, ForbiddenException {
+ List> firedRequests =
+ fireDataRequests(oauth2, projectName, snapshotInfos);
+ List snapshotDataList = new ArrayList<>();
+ for (CompletableFuture fired : firedRequests) {
+ snapshotDataList.add(fired.join().getSnapshotData());
}
+ return snapshotDataList;
+ }
- public Deque getSnapshots(
- Optional oauth2,
- String projectName,
- int afterVersionId
- ) throws GitUserException, FailedConnectionException {
- List snapshotInfos = getSnapshotInfosAfterVersion(
- oauth2,
- projectName,
- afterVersionId
- );
- List snapshotDatas = getMatchingSnapshotData(
- oauth2,
- projectName,
- snapshotInfos
- );
- return combine(snapshotInfos, snapshotDatas);
+ private List> fireDataRequests(
+ Optional oauth2, String projectName, List snapshotInfos) {
+ return snapshotInfos.stream()
+ .map(snap -> api.getForVersion(oauth2, projectName, snap.getVersionId()))
+ .collect(Collectors.toList());
+ }
+
+ private static Deque combine(
+ List snapshotInfos, List snapshotDatas) {
+ Deque snapshots = new LinkedList<>();
+ Iterator infos = snapshotInfos.iterator();
+ Iterator datas = snapshotDatas.iterator();
+ while (infos.hasNext()) {
+ snapshots.add(new Snapshot(infos.next(), datas.next()));
}
-
- public PushResult push(
- Optional oauth2,
- CandidateSnapshot candidateSnapshot,
- String postbackKey
- ) throws MissingRepositoryException, FailedConnectionException, ForbiddenException {
- return SnapshotApi.getResult(api.push(
- oauth2, candidateSnapshot, postbackKey));
- }
-
- private List getSnapshotInfosAfterVersion(
- Optional oauth2,
- String projectName,
- int version
- ) throws FailedConnectionException, GitUserException {
- SortedSet versions = new TreeSet<>();
- CompletableFuture getDoc
- = api.getDoc(oauth2, projectName);
- CompletableFuture savedVers
- = api.getSavedVers(oauth2, projectName);
- GetDocResult latestDoc = SnapshotApi.getResult(getDoc);
- int latest = latestDoc.getVersionID();
- // Handle edge-case for projects with no changes, that were imported
- // to v2. In which case both `latest` and `version` will be zero.
- // See: https://github.com/overleaf/writelatex-git-bridge/pull/50
- if (latest > version || (latest == 0 && version == 0)) {
- for (
- SnapshotInfo snapshotInfo :
- SnapshotApi.getResult(savedVers).getSavedVers()
- ) {
- if (snapshotInfo.getVersionId() > version) {
- versions.add(snapshotInfo);
- }
- }
- versions.add(new SnapshotInfo(
- latest,
- latestDoc.getCreatedAt(),
- latestDoc.getName(),
- latestDoc.getEmail()
- ));
-
- }
- return new ArrayList<>(versions);
- }
-
- private List getMatchingSnapshotData(
- Optional oauth2,
- String projectName,
- List snapshotInfos
- ) throws FailedConnectionException, ForbiddenException {
- List> firedRequests
- = fireDataRequests(oauth2, projectName, snapshotInfos);
- List snapshotDataList = new ArrayList<>();
- for (CompletableFuture fired : firedRequests) {
- snapshotDataList.add(fired.join().getSnapshotData());
- }
- return snapshotDataList;
- }
-
- private List> fireDataRequests(
- Optional oauth2,
- String projectName,
- List snapshotInfos
- ) {
- return snapshotInfos
- .stream()
- .map(snap -> api.getForVersion(
- oauth2, projectName, snap.getVersionId()))
- .collect(Collectors.toList());
- }
-
- private static Deque combine(
- List snapshotInfos,
- List snapshotDatas
- ) {
- Deque snapshots = new LinkedList<>();
- Iterator infos = snapshotInfos.iterator();
- Iterator datas = snapshotDatas.iterator();
- while (infos.hasNext()) {
- snapshots.add(new Snapshot(infos.next(), datas.next()));
- }
- return snapshots;
- }
-
+ return snapshots;
+ }
}
diff --git a/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/swap/job/NoopSwapJob.java b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/swap/job/NoopSwapJob.java
index 49ebf0c58b..977734a42c 100644
--- a/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/swap/job/NoopSwapJob.java
+++ b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/swap/job/NoopSwapJob.java
@@ -1,20 +1,19 @@
package uk.ac.ic.wlgitbridge.bridge.swap.job;
-/**
+/*
* Created by winston on 24/08/2016.
*/
public class NoopSwapJob implements SwapJob {
- @Override
- public void start() {}
+ @Override
+ public void start() {}
- @Override
- public void stop() {}
+ @Override
+ public void stop() {}
- @Override
- public void evict(String projName) {}
-
- @Override
- public void restore(String projName) {}
+ @Override
+ public void evict(String projName) {}
+ @Override
+ public void restore(String projName) {}
}
diff --git a/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/swap/job/SwapJob.java b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/swap/job/SwapJob.java
index d671e50fc2..8afaf1721a 100644
--- a/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/swap/job/SwapJob.java
+++ b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/swap/job/SwapJob.java
@@ -1,129 +1,124 @@
package uk.ac.ic.wlgitbridge.bridge.swap.job;
+import java.io.IOException;
+import java.util.Optional;
import uk.ac.ic.wlgitbridge.bridge.db.DBStore;
import uk.ac.ic.wlgitbridge.bridge.lock.ProjectLock;
import uk.ac.ic.wlgitbridge.bridge.repo.RepoStore;
import uk.ac.ic.wlgitbridge.bridge.swap.store.SwapStore;
import uk.ac.ic.wlgitbridge.util.Log;
-import java.io.IOException;
-import java.util.Optional;
-
-/**
+/*
* Created by winston on 20/08/2016.
*/
public interface SwapJob {
- enum CompressionMethod { Bzip2, Gzip }
+ enum CompressionMethod {
+ Bzip2,
+ Gzip
+ }
- static CompressionMethod stringToCompressionMethod(String compressionString) {
- if (compressionString == null) {
- return null;
- }
- CompressionMethod result;
- switch (compressionString) {
- case "gzip":
- result = CompressionMethod.Gzip;
- break;
- case "bzip2":
- result = CompressionMethod.Bzip2;
- break;
- default:
- result = null;
- break;
- }
- return result;
+ static CompressionMethod stringToCompressionMethod(String compressionString) {
+ if (compressionString == null) {
+ return null;
}
-
- static String compressionMethodAsString(CompressionMethod compressionMethod) {
- if (compressionMethod == null) {
- return null;
- }
- String result;
- switch (compressionMethod) {
- case Gzip:
- result = "gzip";
- break;
- case Bzip2:
- result = "bzip2";
- break;
- default:
- result = null;
- break;
- }
- return result;
+ CompressionMethod result;
+ switch (compressionString) {
+ case "gzip":
+ result = CompressionMethod.Gzip;
+ break;
+ case "bzip2":
+ result = CompressionMethod.Bzip2;
+ break;
+ default:
+ result = null;
+ break;
}
+ return result;
+ }
- static SwapJob fromConfig(
- Optional cfg,
- ProjectLock lock,
- RepoStore repoStore,
- DBStore dbStore,
- SwapStore swapStore
- ) {
- if (!cfg.isPresent()) {
- return new NoopSwapJob();
- }
- if (!swapStore.isSafe() && !cfg.get().getAllowUnsafeStores()) {
- Log.warn("Swap store '{}' is not safe; disabling swap job", swapStore.getClass().getSimpleName());
- return new NoopSwapJob();
- }
- return new SwapJobImpl(
- cfg.get(),
- lock,
- repoStore,
- dbStore,
- swapStore
- );
+ static String compressionMethodAsString(CompressionMethod compressionMethod) {
+ if (compressionMethod == null) {
+ return null;
}
+ String result;
+ switch (compressionMethod) {
+ case Gzip:
+ result = "gzip";
+ break;
+ case Bzip2:
+ result = "bzip2";
+ break;
+ default:
+ result = null;
+ break;
+ }
+ return result;
+ }
- /**
- * Starts the swap job, which should schedule an attempted swap at the given
- * configured interval (config["swapJob"]["intervalMillis"]
- */
- void start();
+ static SwapJob fromConfig(
+ Optional cfg,
+ ProjectLock lock,
+ RepoStore repoStore,
+ DBStore dbStore,
+ SwapStore swapStore) {
+ if (!cfg.isPresent()) {
+ return new NoopSwapJob();
+ }
+ if (!swapStore.isSafe() && !cfg.get().getAllowUnsafeStores()) {
+ Log.warn(
+ "Swap store '{}' is not safe; disabling swap job", swapStore.getClass().getSimpleName());
+ return new NoopSwapJob();
+ }
+ return new SwapJobImpl(cfg.get(), lock, repoStore, dbStore, swapStore);
+ }
- /**
- * Stops the stop job.
- */
- void stop();
+ /*
+ * Starts the swap job, which should schedule an attempted swap at the given
+ * configured interval (config["swapJob"]["intervalMillis"]
+ */
+ void start();
- /**
- * Called by the swap job when a project should be evicted.
- *
- * Pre:
- * 1. projName must be in repoStore
- * 2. projName should not be in swapStore
- * 3. projName should be PRESENT in dbStore (last_accessed is not null)
- *
- * Acquires the project lock and performs an eviction of projName.
- *
- * Post:
- * 1. projName should not in repoStore
- * 2. projName must be in swapStore
- * 3. projName must be SWAPPED in dbStore (last_accessed is null)
- * @param projName
- * @throws IOException
- */
- void evict(String projName) throws IOException;
+ /*
+ * Stops the stop job.
+ */
+ void stop();
- /**
- * Called on a project when it must be restored.
- *
- * Pre:
- * 1. projName should not be in repoStore
- * 2. projName must be in swapStore
- * 3. projName must be SWAPPED in dbStore (last_accessed is null)
- *
- * Acquires the project lock and restores projName.
- *
- * Post:
- * 1. projName must be in repoStore
- * 2. projName should not in swapStore
- * 3. projName should be PRESENT in dbStore (last_accessed is not null)
- * @param projName
- * @throws IOException
- */
- void restore(String projName) throws IOException;
+ /*
+ * Called by the swap job when a project should be evicted.
+ *
+ * Pre:
+ * 1. projName must be in repoStore
+ * 2. projName should not be in swapStore
+ * 3. projName should be PRESENT in dbStore (last_accessed is not null)
+ *
+ * Acquires the project lock and performs an eviction of projName.
+ *
+ * Post:
+ * 1. projName should not in repoStore
+ * 2. projName must be in swapStore
+ * 3. projName must be SWAPPED in dbStore (last_accessed is null)
+ * @param projName
+ * @throws IOException
+ */
+ void evict(String projName) throws IOException;
+ /*
+ * Called on a project when it must be restored.
+ *
+ * Pre:
+ * 1. projName should not be in repoStore
+ * 2. projName must be in swapStore
+ * 3. projName must be SWAPPED in dbStore (last_accessed is null)
+ *
+ * Acquires the project lock and restores projName.
+ *
+ * Post:
+ * 1. projName must be in repoStore
+ * 2. projName should not in swapStore
+ * 3. projName should be PRESENT in dbStore (last_accessed is not null)
+ * @param projName
+ * @throws IOException
+ */
+ void restore(String projName) throws IOException;
}
diff --git a/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/swap/job/SwapJobConfig.java b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/swap/job/SwapJobConfig.java
index c517a23761..369bf5c12f 100644
--- a/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/swap/job/SwapJobConfig.java
+++ b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/swap/job/SwapJobConfig.java
@@ -1,62 +1,63 @@
package uk.ac.ic.wlgitbridge.bridge.swap.job;
-import uk.ac.ic.wlgitbridge.util.Log;
import uk.ac.ic.wlgitbridge.bridge.swap.job.SwapJob.CompressionMethod;
+import uk.ac.ic.wlgitbridge.util.Log;
-/**
+/*
* Created by winston on 23/08/2016.
*/
public class SwapJobConfig {
- private final int minProjects;
- private final int lowGiB;
- private final int highGiB;
- private final long intervalMillis;
- private final String compressionMethod;
- private final boolean allowUnsafeStores;
+ private final int minProjects;
+ private final int lowGiB;
+ private final int highGiB;
+ private final long intervalMillis;
+ private final String compressionMethod;
+ private final boolean allowUnsafeStores;
- public SwapJobConfig(
- int minProjects,
- int lowGiB,
- int highGiB,
- long intervalMillis,
- String compressionMethod,
- boolean allowUnsafeStores
- ) {
- this.minProjects = minProjects;
- this.lowGiB = lowGiB;
- this.highGiB = highGiB;
- this.intervalMillis = intervalMillis;
- this.compressionMethod = compressionMethod;
- this.allowUnsafeStores = allowUnsafeStores;
- }
+ public SwapJobConfig(
+ int minProjects,
+ int lowGiB,
+ int highGiB,
+ long intervalMillis,
+ String compressionMethod,
+ boolean allowUnsafeStores) {
+ this.minProjects = minProjects;
+ this.lowGiB = lowGiB;
+ this.highGiB = highGiB;
+ this.intervalMillis = intervalMillis;
+ this.compressionMethod = compressionMethod;
+ this.allowUnsafeStores = allowUnsafeStores;
+ }
- public int getMinProjects() {
- return minProjects;
- }
+ public int getMinProjects() {
+ return minProjects;
+ }
- public int getLowGiB() {
- return lowGiB;
- }
+ public int getLowGiB() {
+ return lowGiB;
+ }
- public int getHighGiB() {
- return highGiB;
- }
+ public int getHighGiB() {
+ return highGiB;
+ }
- public long getIntervalMillis() {
- return intervalMillis;
- }
+ public long getIntervalMillis() {
+ return intervalMillis;
+ }
- public boolean getAllowUnsafeStores() {
- return allowUnsafeStores;
- }
+ public boolean getAllowUnsafeStores() {
+ return allowUnsafeStores;
+ }
- public SwapJob.CompressionMethod getCompressionMethod() {
- CompressionMethod result = SwapJob.stringToCompressionMethod(compressionMethod);
- if (result == null) {
- Log.info("SwapJobConfig: un-supported compressionMethod '{}', default to 'bzip2'", compressionMethod);
- result = CompressionMethod.Bzip2;
- }
- return result;
+ public SwapJob.CompressionMethod getCompressionMethod() {
+ CompressionMethod result = SwapJob.stringToCompressionMethod(compressionMethod);
+ if (result == null) {
+ Log.info(
+ "SwapJobConfig: un-supported compressionMethod '{}', default to 'bzip2'",
+ compressionMethod);
+ result = CompressionMethod.Bzip2;
}
+ return result;
+ }
}
diff --git a/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/swap/job/SwapJobImpl.java b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/swap/job/SwapJobImpl.java
index 6b42cac521..7101f8a8b5 100644
--- a/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/swap/job/SwapJobImpl.java
+++ b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/swap/job/SwapJobImpl.java
@@ -1,6 +1,14 @@
package uk.ac.ic.wlgitbridge.bridge.swap.job;
import com.google.api.client.repackaged.com.google.common.base.Preconditions;
+import java.io.IOException;
+import java.io.InputStream;
+import java.sql.Timestamp;
+import java.time.Duration;
+import java.time.LocalDateTime;
+import java.util.ArrayList;
+import java.util.Timer;
+import java.util.concurrent.atomic.AtomicInteger;
import uk.ac.ic.wlgitbridge.bridge.db.DBStore;
import uk.ac.ic.wlgitbridge.bridge.lock.LockGuard;
import uk.ac.ic.wlgitbridge.bridge.lock.ProjectLock;
@@ -10,259 +18,228 @@ import uk.ac.ic.wlgitbridge.data.CannotAcquireLockException;
import uk.ac.ic.wlgitbridge.util.Log;
import uk.ac.ic.wlgitbridge.util.TimerUtils;
-import java.io.IOException;
-import java.io.InputStream;
-import java.sql.Timestamp;
-import java.time.Duration;
-import java.time.LocalDateTime;
-import java.util.ArrayList;
-import java.util.Timer;
-import java.util.concurrent.atomic.AtomicInteger;
-
-/**
+/*
* Created by winston on 20/08/2016.
*/
public class SwapJobImpl implements SwapJob {
- private static final long GiB = (1l << 30);
+ private static final long GiB = (1l << 30);
- int minProjects;
- long lowWatermarkBytes;
- long highWatermarkBytes;
- Duration interval;
+ int minProjects;
+ long lowWatermarkBytes;
+ long highWatermarkBytes;
+ Duration interval;
- private final ProjectLock lock;
- private final RepoStore repoStore;
- private final DBStore dbStore;
- private final SwapStore swapStore;
- private final CompressionMethod compressionMethod;
+ private final ProjectLock lock;
+ private final RepoStore repoStore;
+ private final DBStore dbStore;
+ private final SwapStore swapStore;
+ private final CompressionMethod compressionMethod;
- private final Timer timer;
+ private final Timer timer;
- final AtomicInteger swaps;
+ final AtomicInteger swaps;
- public SwapJobImpl(
- SwapJobConfig cfg,
- ProjectLock lock,
- RepoStore repoStore,
- DBStore dbStore,
- SwapStore swapStore
- ) {
- this(
- cfg.getMinProjects(),
- GiB * cfg.getLowGiB(),
- GiB * cfg.getHighGiB(),
- Duration.ofMillis(cfg.getIntervalMillis()),
- cfg.getCompressionMethod(),
- lock,
- repoStore,
- dbStore,
- swapStore
- );
+ public SwapJobImpl(
+ SwapJobConfig cfg,
+ ProjectLock lock,
+ RepoStore repoStore,
+ DBStore dbStore,
+ SwapStore swapStore) {
+ this(
+ cfg.getMinProjects(),
+ GiB * cfg.getLowGiB(),
+ GiB * cfg.getHighGiB(),
+ Duration.ofMillis(cfg.getIntervalMillis()),
+ cfg.getCompressionMethod(),
+ lock,
+ repoStore,
+ dbStore,
+ swapStore);
+ }
+
+ SwapJobImpl(
+ int minProjects,
+ long lowWatermarkBytes,
+ long highWatermarkBytes,
+ Duration interval,
+ CompressionMethod method,
+ ProjectLock lock,
+ RepoStore repoStore,
+ DBStore dbStore,
+ SwapStore swapStore) {
+ this.minProjects = minProjects;
+ this.lowWatermarkBytes = lowWatermarkBytes;
+ this.highWatermarkBytes = highWatermarkBytes;
+ this.interval = interval;
+ this.compressionMethod = method;
+ this.lock = lock;
+ this.repoStore = repoStore;
+ this.dbStore = dbStore;
+ this.swapStore = swapStore;
+ timer = new Timer();
+ swaps = new AtomicInteger(0);
+ }
+
+ @Override
+ public void start() {
+ timer.schedule(TimerUtils.makeTimerTask(this::doSwap), 0);
+ }
+
+ @Override
+ public void stop() {
+ timer.cancel();
+ }
+
+ private void doSwap() {
+ try {
+ doSwap_();
+ } catch (Throwable t) {
+ Log.warn("Exception thrown during swap job", t);
}
+ timer.schedule(TimerUtils.makeTimerTask(this::doSwap), interval.toMillis());
+ }
- SwapJobImpl(
- int minProjects,
- long lowWatermarkBytes,
- long highWatermarkBytes,
- Duration interval,
- CompressionMethod method,
- ProjectLock lock,
- RepoStore repoStore,
- DBStore dbStore,
- SwapStore swapStore
- ) {
- this.minProjects = minProjects;
- this.lowWatermarkBytes = lowWatermarkBytes;
- this.highWatermarkBytes = highWatermarkBytes;
- this.interval = interval;
- this.compressionMethod = method;
- this.lock = lock;
- this.repoStore = repoStore;
- this.dbStore = dbStore;
- this.swapStore = swapStore;
- timer = new Timer();
- swaps = new AtomicInteger(0);
+ private void doSwap_() {
+ ArrayList exceptionProjectNames = new ArrayList();
+
+ Log.debug("Running swap number {}", swaps.get() + 1);
+ long totalSize = repoStore.totalSize();
+ Log.debug("Size is {}/{} (high)", totalSize, highWatermarkBytes);
+ if (totalSize < highWatermarkBytes) {
+ Log.debug("No need to swap.");
+ swaps.incrementAndGet();
+ return;
}
-
- @Override
- public void start() {
- timer.schedule(
- TimerUtils.makeTimerTask(this::doSwap),
- 0
- );
- }
-
- @Override
- public void stop() {
- timer.cancel();
- }
-
- private void doSwap() {
- try {
- doSwap_();
- } catch (Throwable t) {
- Log.warn("Exception thrown during swap job", t);
+ int numProjects = dbStore.getNumProjects();
+ // while we have too many projects on disk
+ while ((totalSize = repoStore.totalSize()) > lowWatermarkBytes
+ && (numProjects = dbStore.getNumUnswappedProjects()) > minProjects) {
+ // check if we've had too many exceptions so far
+ if (exceptionProjectNames.size() >= 20) {
+ StringBuilder sb = new StringBuilder();
+ for (String s : exceptionProjectNames) {
+ sb.append(s);
+ sb.append(' ');
}
- timer.schedule(
- TimerUtils.makeTimerTask(this::doSwap),
- interval.toMillis()
- );
+ Log.error(
+ "Too many exceptions while running swap, giving up on this run: {}", sb.toString());
+ break;
+ }
+ // get the oldest project and try to swap it
+ String projectName = dbStore.getOldestUnswappedProject();
+ try {
+ evict(projectName);
+ } catch (Exception e) {
+ Log.warn("[{}] Exception while swapping, mark project and move on", projectName, e);
+ // NOTE: this is something of a hack. If a project fails to swap we get stuck in a
+ // loop where `dbStore.getOldestUnswappedProject()` gives the same failing project over and
+ // over again,
+ // which fills up the disk with errors. By touching the access time we can mark the project
+ // as a
+ // non-candidate for swapping. Ideally we should be checking the logs for these log events
+ // and fixing
+ // whatever is wrong with the project
+ dbStore.setLastAccessedTime(projectName, Timestamp.valueOf(LocalDateTime.now()));
+ exceptionProjectNames.add(projectName);
+ }
}
-
- private void doSwap_() {
- ArrayList exceptionProjectNames = new ArrayList();
-
- Log.debug("Running swap number {}", swaps.get() + 1);
- long totalSize = repoStore.totalSize();
- Log.debug("Size is {}/{} (high)", totalSize, highWatermarkBytes);
- if (totalSize < highWatermarkBytes) {
- Log.debug("No need to swap.");
- swaps.incrementAndGet();
- return;
- }
- int numProjects = dbStore.getNumProjects();
- // while we have too many projects on disk
- while (
- (totalSize = repoStore.totalSize()) > lowWatermarkBytes &&
- (numProjects = dbStore.getNumUnswappedProjects()) > minProjects
- ) {
- // check if we've had too many exceptions so far
- if (exceptionProjectNames.size() >= 20) {
- StringBuilder sb = new StringBuilder();
- for (String s: exceptionProjectNames) {
- sb.append(s);
- sb.append(' ');
- }
- Log.error(
- "Too many exceptions while running swap, giving up on this run: {}",
- sb.toString()
- );
- break;
- }
- // get the oldest project and try to swap it
- String projectName = dbStore.getOldestUnswappedProject();
- try {
- evict(projectName);
- } catch (Exception e) {
- Log.warn("[{}] Exception while swapping, mark project and move on", projectName, e);
- // NOTE: this is something of a hack. If a project fails to swap we get stuck in a
- // loop where `dbStore.getOldestUnswappedProject()` gives the same failing project over and over again,
- // which fills up the disk with errors. By touching the access time we can mark the project as a
- // non-candidate for swapping. Ideally we should be checking the logs for these log events and fixing
- // whatever is wrong with the project
- dbStore.setLastAccessedTime(
- projectName,
- Timestamp.valueOf(LocalDateTime.now())
- );
- exceptionProjectNames.add(projectName);
- }
- }
- if (totalSize > lowWatermarkBytes) {
- Log.warn(
- "Finished swapping, but total size is still too high."
- );
- }
- Log.debug(
- "Size: {}/{} (low), " +
- "{} (high), " +
- "projects on disk: {}/{}, " +
- "min projects on disk: {}",
- totalSize,
- lowWatermarkBytes,
- highWatermarkBytes,
- numProjects,
- dbStore.getNumProjects(),
- minProjects
- );
- swaps.incrementAndGet();
+ if (totalSize > lowWatermarkBytes) {
+ Log.warn("Finished swapping, but total size is still too high.");
}
+ Log.debug(
+ "Size: {}/{} (low), "
+ + "{} (high), "
+ + "projects on disk: {}/{}, "
+ + "min projects on disk: {}",
+ totalSize,
+ lowWatermarkBytes,
+ highWatermarkBytes,
+ numProjects,
+ dbStore.getNumProjects(),
+ minProjects);
+ swaps.incrementAndGet();
+ }
- /**
- * @see SwapJob#evict(String) for high-level description.
- *
- * 1. Acquires the project lock.
- * 2. Gets a bz2 stream and size of a project from the repo store, or throws
- * 3. Uploads the bz2 stream and size to the projName in the swapStore.
- * 4. Sets the last accessed time in the dbStore to null, which makes our
- * state SWAPPED
- * 5. Removes the project from the repo store.
- * @param projName
- * @throws IOException
- */
- @Override
- public void evict(String projName) throws IOException {
- Preconditions.checkNotNull(projName, "projName was null");
- Log.info("Evicting project: {}", projName);
- try (LockGuard __ = lock.lockGuard(projName)) {
- try {
- repoStore.gcProject(projName);
- } catch (Exception e) {
- Log.error("[{}] Exception while running gc on project: {}", projName, e);
- }
- long[] sizePtr = new long[1];
- try (InputStream blob = getBlobStream(projName, sizePtr)) {
- swapStore.upload(projName, blob, sizePtr[0]);
- String compression = SwapJob.compressionMethodAsString(compressionMethod);
- if (compression == null) {
- throw new RuntimeException("invalid compression method, should not happen");
- }
- dbStore.swap(projName, compression);
- repoStore.remove(projName);
- }
- } catch (CannotAcquireLockException e) {
- Log.warn("[{}] Cannot acquire project lock, skipping swap", projName);
- return;
- }
- Log.info("Evicted project: {}", projName);
- }
-
- private InputStream getBlobStream(String projName, long[] sizePtr) throws IOException {
- if (compressionMethod == CompressionMethod.Gzip) {
- return repoStore.gzipProject(projName, sizePtr);
- } else if (compressionMethod == CompressionMethod.Bzip2) {
- return repoStore.bzip2Project(projName, sizePtr);
- } else {
+ /*
+ * @see SwapJob#evict(String) for high-level description.
+ *
+ * 1. Acquires the project lock.
+ * 2. Gets a bz2 stream and size of a project from the repo store, or throws
+ * 3. Uploads the bz2 stream and size to the projName in the swapStore.
+ * 4. Sets the last accessed time in the dbStore to null, which makes our
+ * state SWAPPED
+ * 5. Removes the project from the repo store.
+ * @param projName
+ * @throws IOException
+ */
+ @Override
+ public void evict(String projName) throws IOException {
+ Preconditions.checkNotNull(projName, "projName was null");
+ Log.info("Evicting project: {}", projName);
+ try (LockGuard __ = lock.lockGuard(projName)) {
+ try {
+ repoStore.gcProject(projName);
+ } catch (Exception e) {
+ Log.error("[{}] Exception while running gc on project: {}", projName, e);
+ }
+ long[] sizePtr = new long[1];
+ try (InputStream blob = getBlobStream(projName, sizePtr)) {
+ swapStore.upload(projName, blob, sizePtr[0]);
+ String compression = SwapJob.compressionMethodAsString(compressionMethod);
+ if (compression == null) {
throw new RuntimeException("invalid compression method, should not happen");
}
+ dbStore.swap(projName, compression);
+ repoStore.remove(projName);
+ }
+ } catch (CannotAcquireLockException e) {
+ Log.warn("[{}] Cannot acquire project lock, skipping swap", projName);
+ return;
}
+ Log.info("Evicted project: {}", projName);
+ }
- /**
- * @see SwapJob#restore(String) for high-level description.
- *
- * 1. Acquires the project lock.
- * 2. Gets a bz2 stream for the project from the swapStore.
- * 3. Fully downloads and places the bz2 stream back in the repo store.
- * 4. Sets the last accessed time in the dbStore to now, which makes our
- * state PRESENT and the last project to be evicted.
- * @param projName
- * @throws IOException
- */
- @Override
- public void restore(String projName) throws IOException {
- try (LockGuard __ = lock.lockGuard(projName)) {
- try (InputStream zipped = swapStore.openDownloadStream(projName)) {
- String compression = dbStore.getSwapCompression(projName);
- if (compression == null) {
- throw new RuntimeException("Missing compression method during restore, should not happen");
- }
- if ("gzip".equals(compression)) {
- repoStore.ungzipProject(
- projName,
- zipped
- );
- } else if ("bzip2".equals(compression)) {
- repoStore.unbzip2Project(
- projName,
- zipped
- );
- }
- swapStore.remove(projName);
- dbStore.restore(projName);
- }
- } catch (CannotAcquireLockException e) {
- throw new RuntimeException(e);
+ private InputStream getBlobStream(String projName, long[] sizePtr) throws IOException {
+ if (compressionMethod == CompressionMethod.Gzip) {
+ return repoStore.gzipProject(projName, sizePtr);
+ } else if (compressionMethod == CompressionMethod.Bzip2) {
+ return repoStore.bzip2Project(projName, sizePtr);
+ } else {
+ throw new RuntimeException("invalid compression method, should not happen");
+ }
+ }
+
+ /*
+ * @see SwapJob#restore(String) for high-level description.
+ *
+ * 1. Acquires the project lock.
+ * 2. Gets a bz2 stream for the project from the swapStore.
+ * 3. Fully downloads and places the bz2 stream back in the repo store.
+ * 4. Sets the last accessed time in the dbStore to now, which makes our
+ * state PRESENT and the last project to be evicted.
+ * @param projName
+ * @throws IOException
+ */
+ @Override
+ public void restore(String projName) throws IOException {
+ try (LockGuard __ = lock.lockGuard(projName)) {
+ try (InputStream zipped = swapStore.openDownloadStream(projName)) {
+ String compression = dbStore.getSwapCompression(projName);
+ if (compression == null) {
+ throw new RuntimeException(
+ "Missing compression method during restore, should not happen");
}
+ if ("gzip".equals(compression)) {
+ repoStore.ungzipProject(projName, zipped);
+ } else if ("bzip2".equals(compression)) {
+ repoStore.unbzip2Project(projName, zipped);
+ }
+ swapStore.remove(projName);
+ dbStore.restore(projName);
+ }
+ } catch (CannotAcquireLockException e) {
+ throw new RuntimeException(e);
}
-
+ }
}
diff --git a/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/swap/store/InMemorySwapStore.java b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/swap/store/InMemorySwapStore.java
index e3940840a5..3c7ae0164b 100644
--- a/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/swap/store/InMemorySwapStore.java
+++ b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/swap/store/InMemorySwapStore.java
@@ -1,58 +1,49 @@
package uk.ac.ic.wlgitbridge.bridge.swap.store;
-import org.apache.commons.io.IOUtils;
-
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;
+import org.apache.commons.io.IOUtils;
-/**
+/*
* Created by winston on 23/08/2016.
*/
public class InMemorySwapStore implements SwapStore {
- private final Map store;
+ private final Map store;
- public InMemorySwapStore() {
- store = new HashMap<>();
- }
+ public InMemorySwapStore() {
+ store = new HashMap<>();
+ }
- public InMemorySwapStore(SwapStoreConfig __) {
- this();
- }
+ public InMemorySwapStore(SwapStoreConfig __) {
+ this();
+ }
- @Override
- public void upload(
- String projectName,
- InputStream uploadStream,
- long contentLength
- ) throws IOException {
- store.put(
- projectName,
- IOUtils.toByteArray(uploadStream, contentLength)
- );
- }
+ @Override
+ public void upload(String projectName, InputStream uploadStream, long contentLength)
+ throws IOException {
+ store.put(projectName, IOUtils.toByteArray(uploadStream, contentLength));
+ }
- @Override
- public InputStream openDownloadStream(String projectName) {
- byte[] buf = store.get(projectName);
- if (buf == null) {
- throw new IllegalArgumentException(
- "no such project in swap store: " + projectName
- );
- }
- return new ByteArrayInputStream(buf);
+ @Override
+ public InputStream openDownloadStream(String projectName) {
+ byte[] buf = store.get(projectName);
+ if (buf == null) {
+ throw new IllegalArgumentException("no such project in swap store: " + projectName);
}
+ return new ByteArrayInputStream(buf);
+ }
- @Override
- public void remove(String projectName) {
- store.remove(projectName);
- }
+ @Override
+ public void remove(String projectName) {
+ store.remove(projectName);
+ }
- @Override
- public boolean isSafe() {
- return false;
- }
+ @Override
+ public boolean isSafe() {
+ return false;
+ }
}
diff --git a/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/swap/store/NoopSwapStore.java b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/swap/store/NoopSwapStore.java
index a03c0ce704..b607b483b7 100644
--- a/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/swap/store/NoopSwapStore.java
+++ b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/swap/store/NoopSwapStore.java
@@ -3,30 +3,26 @@ package uk.ac.ic.wlgitbridge.bridge.swap.store;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
-/**
+/*
* Created by winston on 24/08/2016.
*/
public class NoopSwapStore implements SwapStore {
- public NoopSwapStore(SwapStoreConfig __) {}
+ public NoopSwapStore(SwapStoreConfig __) {}
- @Override
- public void upload(
- String projectName,
- InputStream uploadStream,
- long contentLength
- ) {}
+ @Override
+ public void upload(String projectName, InputStream uploadStream, long contentLength) {}
- @Override
- public InputStream openDownloadStream(String projectName) {
- return new ByteArrayInputStream(new byte[0]);
- }
+ @Override
+ public InputStream openDownloadStream(String projectName) {
+ return new ByteArrayInputStream(new byte[0]);
+ }
- @Override
- public void remove(String projectName) {}
+ @Override
+ public void remove(String projectName) {}
- @Override
- public boolean isSafe() {
- return false;
- }
+ @Override
+ public boolean isSafe() {
+ return false;
+ }
}
diff --git a/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/swap/store/S3SwapStore.java b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/swap/store/S3SwapStore.java
index 4c0820d0cc..34e87dbe13 100644
--- a/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/swap/store/S3SwapStore.java
+++ b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/swap/store/S3SwapStore.java
@@ -5,86 +5,60 @@ import com.amazonaws.auth.BasicAWSCredentials;
import com.amazonaws.services.s3.AmazonS3;
import com.amazonaws.services.s3.AmazonS3ClientBuilder;
import com.amazonaws.services.s3.model.*;
-
import java.io.InputStream;
-/**
+/*
* Created by winston on 21/08/2016.
*/
public class S3SwapStore implements SwapStore {
- private final AmazonS3 s3;
+ private final AmazonS3 s3;
- private final String bucketName;
+ private final String bucketName;
- public S3SwapStore(SwapStoreConfig cfg) {
- this(
- cfg.getAwsAccessKey(),
- cfg.getAwsSecret(),
- cfg.getS3BucketName(),
- cfg.getAwsRegion()
- );
+ public S3SwapStore(SwapStoreConfig cfg) {
+ this(cfg.getAwsAccessKey(), cfg.getAwsSecret(), cfg.getS3BucketName(), cfg.getAwsRegion());
+ }
+
+ S3SwapStore(String accessKey, String secret, String bucketName, String region) {
+ String regionToUse = null;
+ if (region == null) {
+ regionToUse = "us-east-1";
+ } else {
+ regionToUse = region;
}
+ s3 =
+ AmazonS3ClientBuilder.standard()
+ .withRegion(regionToUse)
+ .withCredentials(
+ new AWSStaticCredentialsProvider(new BasicAWSCredentials(accessKey, secret)))
+ .build();
+ this.bucketName = bucketName;
+ }
- S3SwapStore(
- String accessKey,
- String secret,
- String bucketName,
- String region
- ) {
- String regionToUse = null;
- if (region == null) {
- regionToUse = "us-east-1";
- } else {
- regionToUse = region;
- }
- s3 = AmazonS3ClientBuilder
- .standard()
- .withRegion(regionToUse)
- .withCredentials(
- new AWSStaticCredentialsProvider(new BasicAWSCredentials(accessKey, secret))
- ).build();
- this.bucketName = bucketName;
- }
+ @Override
+ public void upload(String projectName, InputStream uploadStream, long contentLength) {
+ ObjectMetadata metadata = new ObjectMetadata();
+ metadata.setContentLength(contentLength);
+ PutObjectRequest put = new PutObjectRequest(bucketName, projectName, uploadStream, metadata);
+ PutObjectResult res = s3.putObject(put);
+ }
- @Override
- public void upload(
- String projectName,
- InputStream uploadStream,
- long contentLength
- ) {
- ObjectMetadata metadata = new ObjectMetadata();
- metadata.setContentLength(contentLength);
- PutObjectRequest put = new PutObjectRequest(
- bucketName,
- projectName,
- uploadStream,
- metadata
- );
- PutObjectResult res = s3.putObject(put);
- }
+ @Override
+ public InputStream openDownloadStream(String projectName) {
+ GetObjectRequest get = new GetObjectRequest(bucketName, projectName);
+ S3Object res = s3.getObject(get);
+ return res.getObjectContent();
+ }
- @Override
- public InputStream openDownloadStream(String projectName) {
- GetObjectRequest get = new GetObjectRequest(
- bucketName,
- projectName
- );
- S3Object res = s3.getObject(get);
- return res.getObjectContent();
- }
+ @Override
+ public void remove(String projectName) {
+ DeleteObjectRequest del = new DeleteObjectRequest(bucketName, projectName);
+ s3.deleteObject(del);
+ }
- @Override
- public void remove(String projectName) {
- DeleteObjectRequest del = new DeleteObjectRequest(
- bucketName,
- projectName
- );
- s3.deleteObject(del);
- }
-
- @Override
- public boolean isSafe() {
- return true;
- }
+ @Override
+ public boolean isSafe() {
+ return true;
+ }
}
diff --git a/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/swap/store/SwapStore.java b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/swap/store/SwapStore.java
index aa847f1780..3cf7cf26bf 100644
--- a/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/swap/store/SwapStore.java
+++ b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/swap/store/SwapStore.java
@@ -7,45 +7,37 @@ import java.util.Map;
import java.util.Optional;
import java.util.function.Function;
-/**
+/*
* Created by winston on 20/08/2016.
*/
public interface SwapStore {
- Map> swapStores =
- new HashMap>() {
+ Map> swapStores =
+ new HashMap>() {
- {
- put("noop", NoopSwapStore::new);
- put("memory", InMemorySwapStore::new);
- put("s3", S3SwapStore::new);
- }
+ {
+ put("noop", NoopSwapStore::new);
+ put("memory", InMemorySwapStore::new);
+ put("s3", S3SwapStore::new);
+ }
+ };
- };
+ static SwapStore fromConfig(Optional cfg) {
+ SwapStoreConfig cfg_ = cfg.orElse(SwapStoreConfig.NOOP);
+ String type = cfg_.getType();
+ return swapStores.get(type).apply(cfg_);
+ }
- static SwapStore fromConfig(
- Optional cfg
- ) {
- SwapStoreConfig cfg_ = cfg.orElse(SwapStoreConfig.NOOP);
- String type = cfg_.getType();
- return swapStores.get(type).apply(cfg_);
- }
+ void upload(String projectName, InputStream uploadStream, long contentLength) throws IOException;
- void upload(
- String projectName,
- InputStream uploadStream,
- long contentLength
- ) throws IOException;
+ InputStream openDownloadStream(String projectName);
- InputStream openDownloadStream(String projectName);
-
- void remove(String projectName);
-
- /**
- * Returns true if the swap store safely persists swapped projects.
- *
- * Fake swap stores should return false.
- */
- boolean isSafe();
+ void remove(String projectName);
+ /*
+ * Returns true if the swap store safely persists swapped projects.
+ *
+ * Fake swap stores should return false.
+ */
+ boolean isSafe();
}
diff --git a/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/swap/store/SwapStoreConfig.java b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/swap/store/SwapStoreConfig.java
index 7559b240ec..d0cc806423 100644
--- a/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/swap/store/SwapStoreConfig.java
+++ b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/swap/store/SwapStoreConfig.java
@@ -1,85 +1,64 @@
package uk.ac.ic.wlgitbridge.bridge.swap.store;
-/**
+/*
* Created by winston on 24/08/2016.
*/
public class SwapStoreConfig {
- public static final SwapStoreConfig NOOP = new SwapStoreConfig(
- "noop",
- null,
- null,
- null,
- null
- );
+ public static final SwapStoreConfig NOOP = new SwapStoreConfig("noop", null, null, null, null);
- private String type;
- private String awsAccessKey;
- private String awsSecret;
- private String s3BucketName;
- private String awsRegion;
+ private String type;
+ private String awsAccessKey;
+ private String awsSecret;
+ private String s3BucketName;
+ private String awsRegion;
- public SwapStoreConfig() {}
+ public SwapStoreConfig() {}
- public SwapStoreConfig(
- String awsAccessKey,
- String awsSecret,
- String s3BucketName,
- String awsRegion
- ) {
- this(
- "s3",
- awsAccessKey,
- awsSecret,
- s3BucketName,
- awsRegion
- );
- }
+ public SwapStoreConfig(
+ String awsAccessKey, String awsSecret, String s3BucketName, String awsRegion) {
+ this("s3", awsAccessKey, awsSecret, s3BucketName, awsRegion);
+ }
- SwapStoreConfig(
- String type,
- String awsAccessKey,
- String awsSecret,
- String s3BucketName,
- String awsRegion
- ) {
- this.type = type;
- this.awsAccessKey = awsAccessKey;
- this.awsSecret = awsSecret;
- this.s3BucketName = s3BucketName;
- this.awsRegion = awsRegion;
- }
+ SwapStoreConfig(
+ String type, String awsAccessKey, String awsSecret, String s3BucketName, String awsRegion) {
+ this.type = type;
+ this.awsAccessKey = awsAccessKey;
+ this.awsSecret = awsSecret;
+ this.s3BucketName = s3BucketName;
+ this.awsRegion = awsRegion;
+ }
- public String getType() {
- return type;
- }
+ public String getType() {
+ return type;
+ }
- public String getAwsAccessKey() {
- return awsAccessKey;
- }
+ public String getAwsAccessKey() {
+ return awsAccessKey;
+ }
- public String getAwsSecret() {
- return awsSecret;
- }
+ public String getAwsSecret() {
+ return awsSecret;
+ }
- public String getS3BucketName() {
- return s3BucketName;
- }
+ public String getS3BucketName() {
+ return s3BucketName;
+ }
- public String getAwsRegion() { return awsRegion; }
+ public String getAwsRegion() {
+ return awsRegion;
+ }
- public SwapStoreConfig sanitisedCopy() {
- return new SwapStoreConfig(
- type,
- awsAccessKey == null ? null : "",
- awsSecret == null ? null : "",
- s3BucketName,
- awsRegion
- );
- }
+ public SwapStoreConfig sanitisedCopy() {
+ return new SwapStoreConfig(
+ type,
+ awsAccessKey == null ? null : "",
+ awsSecret == null ? null : "