Kaynağa Gözat

Graceful kill with write lock and per project read locks.

Winston Li 11 yıl önce
ebeveyn
işleme
30521b988b

+ 2 - 2
services/git-bridge/.idea/misc.xml

@@ -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>

+ 0 - 2
services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/Main.java

@@ -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.
  */
  */

+ 10 - 0
services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/writelatex/LockAllWaiter.java

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

+ 32 - 0
services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/writelatex/ProjectLock.java

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

+ 30 - 0
services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/writelatex/ShutdownHook.java

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

+ 1 - 0
services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/writelatex/WriteLatexAPI.java

@@ -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