Graceful kill with write lock and per project read locks.

This commit is contained in:
Winston Li 2015-02-21 00:52:20 +00:00
parent ac50c26aef
commit 30521b988b
6 changed files with 75 additions and 4 deletions

View file

@ -3,6 +3,7 @@
<component name="EntryPointsManager">
<entry_points version="2.0" />
</component>
<component name="IdProvider" IDEtalkID="7A88E1BAD9A613745B3F0AE6CAB24EEC" />
<component name="MavenProjectsManager">
<option name="originalFiles">
<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">
<output url="file://$PROJECT_DIR$/out" />
</component>
</project>
</project>

View file

@ -2,8 +2,6 @@ package uk.ac.ic.wlgitbridge;
import uk.ac.ic.wlgitbridge.application.WLGitBridgeApplication;
import java.nio.file.Paths;
/**
* Created by Winston on 01/11/14.
*/

View file

@ -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);
}

View file

@ -4,6 +4,7 @@ import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
/**
* Created by Winston on 20/11/14.
@ -11,17 +12,44 @@ import java.util.concurrent.locks.ReentrantLock;
public class ProjectLock {
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() {
projectLocks = new HashMap<String, Lock>();
rwlock = new ReentrantReadWriteLock();
rlock = rwlock.readLock();
wlock = rwlock.writeLock();
waiting = false;
}
public void lockForProject(String projectName) {
getLockForProjectName(projectName).lock();
rlock.lock();
}
public void unlockForProject(String projectName) {
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) {
@ -33,4 +61,8 @@ public class ProjectLock {
return lock;
}
public void setWaiter(LockAllWaiter waiter) {
this.waiter = waiter;
}
}

View file

@ -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...");
}
}

View file

@ -31,6 +31,7 @@ public class WriteLatexAPI implements WriteLatexDataSource {
this.dataModel = dataModel;
postbackManager = new PostbackManager();
mainProjectLock = new ProjectLock();
Runtime.getRuntime().addShutdownHook(new ShutdownHook(mainProjectLock));
}
@Override