mirror of
https://github.com/overleaf/overleaf.git
synced 2024-11-21 20:47:08 -05:00
Graceful kill with write lock and per project read locks.
This commit is contained in:
parent
ac50c26aef
commit
30521b988b
6 changed files with 75 additions and 4 deletions
|
@ -3,6 +3,7 @@
|
||||||
<component name="EntryPointsManager">
|
<component name="EntryPointsManager">
|
||||||
<entry_points version="2.0" />
|
<entry_points version="2.0" />
|
||||||
</component>
|
</component>
|
||||||
|
<component name="IdProvider" IDEtalkID="7A88E1BAD9A613745B3F0AE6CAB24EEC" />
|
||||||
<component name="MavenProjectsManager">
|
<component name="MavenProjectsManager">
|
||||||
<option name="originalFiles">
|
<option name="originalFiles">
|
||||||
<list>
|
<list>
|
||||||
|
@ -13,5 +14,4 @@
|
||||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_6" assert-keyword="true" jdk-15="true" project-jdk-name="1.7" project-jdk-type="JavaSDK">
|
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_6" assert-keyword="true" jdk-15="true" project-jdk-name="1.7" project-jdk-type="JavaSDK">
|
||||||
<output url="file://$PROJECT_DIR$/out" />
|
<output url="file://$PROJECT_DIR$/out" />
|
||||||
</component>
|
</component>
|
||||||
</project>
|
</project>
|
||||||
|
|
|
@ -2,8 +2,6 @@ package uk.ac.ic.wlgitbridge;
|
||||||
|
|
||||||
import uk.ac.ic.wlgitbridge.application.WLGitBridgeApplication;
|
import uk.ac.ic.wlgitbridge.application.WLGitBridgeApplication;
|
||||||
|
|
||||||
import java.nio.file.Paths;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by Winston on 01/11/14.
|
* Created by Winston on 01/11/14.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -0,0 +1,10 @@
|
||||||
|
package uk.ac.ic.wlgitbridge.writelatex;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by Winston on 21/02/15.
|
||||||
|
*/
|
||||||
|
public interface LockAllWaiter {
|
||||||
|
|
||||||
|
public void threadsRemaining(int threads);
|
||||||
|
|
||||||
|
}
|
|
@ -4,6 +4,7 @@ import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.concurrent.locks.Lock;
|
import java.util.concurrent.locks.Lock;
|
||||||
import java.util.concurrent.locks.ReentrantLock;
|
import java.util.concurrent.locks.ReentrantLock;
|
||||||
|
import java.util.concurrent.locks.ReentrantReadWriteLock;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by Winston on 20/11/14.
|
* Created by Winston on 20/11/14.
|
||||||
|
@ -11,17 +12,44 @@ import java.util.concurrent.locks.ReentrantLock;
|
||||||
public class ProjectLock {
|
public class ProjectLock {
|
||||||
|
|
||||||
private final Map<String, Lock> projectLocks;
|
private final Map<String, Lock> projectLocks;
|
||||||
|
private final ReentrantReadWriteLock rwlock;
|
||||||
|
private final Lock rlock;
|
||||||
|
private final ReentrantReadWriteLock.WriteLock wlock;
|
||||||
|
private LockAllWaiter waiter;
|
||||||
|
private boolean waiting;
|
||||||
|
|
||||||
public ProjectLock() {
|
public ProjectLock() {
|
||||||
projectLocks = new HashMap<String, Lock>();
|
projectLocks = new HashMap<String, Lock>();
|
||||||
|
rwlock = new ReentrantReadWriteLock();
|
||||||
|
rlock = rwlock.readLock();
|
||||||
|
wlock = rwlock.writeLock();
|
||||||
|
waiting = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void lockForProject(String projectName) {
|
public void lockForProject(String projectName) {
|
||||||
getLockForProjectName(projectName).lock();
|
getLockForProjectName(projectName).lock();
|
||||||
|
rlock.lock();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void unlockForProject(String projectName) {
|
public void unlockForProject(String projectName) {
|
||||||
getLockForProjectName(projectName).unlock();
|
getLockForProjectName(projectName).unlock();
|
||||||
|
rlock.unlock();
|
||||||
|
if (waiting) {
|
||||||
|
trySignal();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void trySignal() {
|
||||||
|
int threads = rwlock.getReadLockCount();
|
||||||
|
if (waiter != null && threads > 0) {
|
||||||
|
waiter.threadsRemaining(threads);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void lockAll() {
|
||||||
|
waiting = true;
|
||||||
|
trySignal();
|
||||||
|
wlock.lock();
|
||||||
}
|
}
|
||||||
|
|
||||||
private synchronized Lock getLockForProjectName(String projectName) {
|
private synchronized Lock getLockForProjectName(String projectName) {
|
||||||
|
@ -33,4 +61,8 @@ public class ProjectLock {
|
||||||
return lock;
|
return lock;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setWaiter(LockAllWaiter waiter) {
|
||||||
|
this.waiter = waiter;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,30 @@
|
||||||
|
package uk.ac.ic.wlgitbridge.writelatex;
|
||||||
|
|
||||||
|
import uk.ac.ic.wlgitbridge.util.Util;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by Winston on 21/02/15.
|
||||||
|
*/
|
||||||
|
public class ShutdownHook extends Thread implements LockAllWaiter {
|
||||||
|
|
||||||
|
private final ProjectLock projectLock;
|
||||||
|
|
||||||
|
public ShutdownHook(ProjectLock projectLock) {
|
||||||
|
this.projectLock = projectLock;
|
||||||
|
projectLock.setWaiter(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
Util.sout("Shutdown received.");
|
||||||
|
projectLock.lockAll();
|
||||||
|
Util.sout("No projects to wait for.");
|
||||||
|
Util.sout("Bye");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void threadsRemaining(int threads) {
|
||||||
|
Util.sout("Waiting for " + threads + " projects...");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -31,6 +31,7 @@ public class WriteLatexAPI implements WriteLatexDataSource {
|
||||||
this.dataModel = dataModel;
|
this.dataModel = dataModel;
|
||||||
postbackManager = new PostbackManager();
|
postbackManager = new PostbackManager();
|
||||||
mainProjectLock = new ProjectLock();
|
mainProjectLock = new ProjectLock();
|
||||||
|
Runtime.getRuntime().addShutdownHook(new ShutdownHook(mainProjectLock));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
Loading…
Reference in a new issue