Speculative solution

This commit is contained in:
Shane Kilkelly 2018-11-27 11:35:22 +00:00
parent 19075f18bc
commit 4f3021cca1
6 changed files with 90 additions and 7 deletions

View file

@ -9,6 +9,7 @@
<version>1.0-SNAPSHOT</version>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.test.skip>true</maven.test.skip>
</properties>
<build>
<plugins>

View file

@ -37,6 +37,7 @@ 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.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;
@ -299,7 +300,7 @@ public class Bridge {
* Synchronises the given repository with Overleaf.
*
* It acquires the project lock and calls
* {@link #getUpdatedRepoCritical(Optional, String)}.
* {@link #getUpdatedRepoCritical(Optional, String, GetDocResult)}.
* @param oauth2 The oauth2 to use
* @param projectName The name of the project
* @throws IOException
@ -310,11 +311,13 @@ public class Bridge {
String projectName
) throws IOException, GitUserException {
try (LockGuard __ = lock.lockGuard(projectName)) {
if (!snapshotAPI.projectExists(oauth2, projectName)) {
Optional<GetDocResult> maybeDoc = snapshotAPI.getDoc(oauth2, projectName);
if (!maybeDoc.isPresent()) {
throw new RepositoryNotFoundException(projectName);
}
GetDocResult doc = maybeDoc.get();
Log.info("[{}] Updating repository", projectName);
return getUpdatedRepoCritical(oauth2, projectName);
return getUpdatedRepoCritical(oauth2, projectName, doc);
}
}
@ -346,14 +349,49 @@ public class Bridge {
*/
private ProjectRepo getUpdatedRepoCritical(
Optional<Credential> oauth2,
String projectName
String projectName,
GetDocResult doc
) throws IOException, GitUserException {
ProjectRepo repo;
ProjectState state = dbStore.getProjectState(projectName);
Log.info(">>>> RepoStore {}", repoStore.getRepoStorePath());
Log.info(
">>>> getUpdatedRepoCritical, {} migratedFrom {}",
projectName,
doc.getMigratedFromID()
);
switch (state) {
case NOT_PRESENT:
repo = repoStore.initRepo(projectName);
break;
Log.info(">>>> Not present {}", projectName);
String migratedFromID = doc.getMigratedFromID();
if (migratedFromID != null) {
Log.info(">>>> has a migratedFromId {} {}", projectName, migratedFromID);
ProjectState sourceState = dbStore.getProjectState(migratedFromID);
try (LockGuard __ = lock.lockGuard(migratedFromID)) {
switch (sourceState) {
case NOT_PRESENT:
// Normal init-repo
Log.info(">>>> migrated-from-id not present, proceed as normal");
repo = repoStore.initRepo(projectName);
break;
case SWAPPED:
// Swap back and then copy
Log.info(">>>> migrated-from-id swapped, unswap and proceed");
swapJob.restore(migratedFromID);
/* Fallthrough */
default:
// Copy data, and set version to zero
Log.info(">>>> migrated-from-id init from existing");
repo = repoStore.initRepoFromExisting(projectName, migratedFromID);
dbStore.setLatestVersionForProject(migratedFromID, 0);
}
}
break;
} else {
Log.info(">>>> no migrated-from-id {}", projectName);
repo = repoStore.initRepo(projectName);
break;
}
case SWAPPED:
swapJob.restore(projectName);
/* Fallthrough */

View file

@ -4,6 +4,7 @@ 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;
@ -74,6 +75,38 @@ public class FSGitRepoStore implements RepoStore {
ret, Optional.of(maxFileSize), Optional.empty());
}
@Override
public ProjectRepo initRepoFromExisting(
String project, String fromProject
) throws IOException {
GitProjectRepo ret = GitProjectRepo.fromName(project);
// GitProjectRepo origin = GitProjectRepo.fromName(fromProject);
ret.initRepo(this);
Log.info(">>>> Copy from {} to {}", fromProject, project);
String repoRoot = getRepoStorePath();
String sourcePath = repoRoot + "/" + fromProject;
String destinationPath = repoRoot + "/" + project;
Log.info(">>>> paths from: {} and to: {}", sourcePath, destinationPath);
new ProcessBuilder(
"rm", "-rf",
destinationPath
).start();
Process copyProcess = new ProcessBuilder(
"cp", "-ra",
sourcePath,
destinationPath + "/"
).start();
Log.info(">>>> done copy");
try {
copyProcess.waitFor();
} catch (InterruptedException e) {
e.printStackTrace();
throw new IOException("copy failed" + e.getLocalizedMessage());
}
return new WalkOverrideGitRepo(
ret, Optional.of(maxFileSize), Optional.empty());
}
@Override
public ProjectRepo getExistingRepo(String project) throws IOException {
GitProjectRepo ret = GitProjectRepo.fromName(project);

View file

@ -22,6 +22,8 @@ public interface RepoStore {
ProjectRepo initRepo(String project) throws IOException;
ProjectRepo initRepoFromExisting(String project, String fromProject) throws IOException;
ProjectRepo getExistingRepo(String project) throws IOException;
ProjectRepo useJGitRepo(Repository repo, ObjectId commitId);

View file

@ -44,6 +44,15 @@ public class SnapshotApiFacade {
}
}
public Optional<GetDocResult> getDoc(
Optional<Credential> oauth2,
String projectName
) throws FailedConnectionException, GitUserException {
GetDocResult doc = SnapshotApi
.getResult(api.getDoc(oauth2, projectName));
return Optional.ofNullable(doc);
}
public Deque<Snapshot> getSnapshots(
Optional<Credential> oauth2,
String projectName,

View file

@ -90,7 +90,7 @@ public class WLRepositoryResolver
return bridge.getUpdatedRepo(oauth2, projName).getJGitRepository();
} catch (RepositoryNotFoundException e) {
Log.info("Repository not found: " + name);
throw e;
throw new RepositoryNotFoundException("derp");
/*
} catch (ServiceNotAuthorizedException e) {
cannot occur