You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ofbiz.apache.org by jo...@apache.org on 2007/09/19 05:06:55 UTC

svn commit: r577139 - /ofbiz/trunk/framework/service/src/org/ofbiz/service/semaphore/ServiceSemaphore.java

Author: jonesde
Date: Tue Sep 18 20:06:55 2007
New Revision: 577139

URL: http://svn.apache.org/viewvc?rev=577139&view=rev
Log:
Refactored to use a loop instead of recursion for the retries so the stack doesn't get so huge; also added notes about some things that need to be done on this semaphore stuff

Modified:
    ofbiz/trunk/framework/service/src/org/ofbiz/service/semaphore/ServiceSemaphore.java

Modified: ofbiz/trunk/framework/service/src/org/ofbiz/service/semaphore/ServiceSemaphore.java
URL: http://svn.apache.org/viewvc/ofbiz/trunk/framework/service/src/org/ofbiz/service/semaphore/ServiceSemaphore.java?rev=577139&r1=577138&r2=577139&view=diff
==============================================================================
--- ofbiz/trunk/framework/service/src/org/ofbiz/service/semaphore/ServiceSemaphore.java (original)
+++ ofbiz/trunk/framework/service/src/org/ofbiz/service/semaphore/ServiceSemaphore.java Tue Sep 18 20:06:55 2007
@@ -18,6 +18,9 @@
  * ServiceSemaphore
  */
 public class ServiceSemaphore {
+    // TODO: make sleep and max wait settings configurable per service
+    // TODO: add something to make sure semaphores are cleaned up on failures and when the thread somehow goes away without cleaning it up
+    // TODO: write service engine test cases to make sure semaphore both blocking and timing out (use config to set sleep and wait to low values so it times out quickly)
 
     public static final String module = ServiceSemaphore.class.getName();
     public static final int SEMAPHORE_MODE_FAIL = 0;
@@ -31,11 +34,12 @@
     protected ModelService model;
 
     protected int wait = 0;
-    protected int mode = 2;
+    protected int mode = SEMAPHORE_MODE_NONE;
+    protected Timestamp lockTime = null;
 
     public ServiceSemaphore(GenericDelegator delegator, ModelService model) {
-        this.mode = "wait".equals(model.semaphore) ? 1 : ("fail".equals(model.semaphore) ? 0 : 2);
         this.delegator = delegator;
+        this.mode = "wait".equals(model.semaphore) ? SEMAPHORE_MODE_WAIT : ("fail".equals(model.semaphore) ? SEMAPHORE_MODE_FAIL : SEMAPHORE_MODE_NONE);
         this.model = model;
         this.lock = null;
     }
@@ -43,8 +47,55 @@
     public void acquire() throws SemaphoreWaitException, SemaphoreFailException {
         if (mode == SEMAPHORE_MODE_NONE) return;
 
+        lockTime = UtilDateTime.nowTimestamp();
+        
+        if (this.checkLockNeedToWait()) {
+            waitOrFail();
+        }
+    }
+
+    public void release() throws SemaphoreFailException {
+        if (mode == SEMAPHORE_MODE_NONE) return;
+
+        // remove the lock file
+        dbWrite(lock, true);
+    }
+    
+    private void waitOrFail() throws SemaphoreWaitException, SemaphoreFailException {
+        if (SEMAPHORE_MODE_FAIL == mode) {
+            // fail
+            throw new SemaphoreFailException("Service [" + model.name + "] is locked");
+        } else if (SEMAPHORE_MODE_WAIT == mode) {
+            boolean timedOut = true;
+            while (wait < MAX_WAIT) {
+                wait++;
+                try {
+                    Thread.sleep(SLEEP);               
+                } catch (InterruptedException e) {
+                    Debug.logInfo(e, "Sleep interrupted: ServiceSemaphone.waitOrFail()", module);
+                }
+
+                // try again
+                if (!checkLockNeedToWait()) {
+                    timedOut = false;
+                    break;
+                }
+            }
+            if (timedOut) {
+                double waitTimeSec = ((double) (System.currentTimeMillis() - lockTime.getTime()) / 1000.0);
+                String errMsg = "Service [" + model.name + "] with wait semaphore exceeded wait timeout, waited [" + waitTimeSec + "], wait started at " + lockTime;
+                Debug.logWarning(errMsg, module);
+                throw new SemaphoreWaitException(errMsg);
+            }
+        } else if (SEMAPHORE_MODE_NONE == mode) {
+            Debug.logWarning("Semaphore mode [none] attempted to aquire a lock; but should not have!", module);
+        } else {
+            throw new SemaphoreFailException("Found invalid Semaphore mode [" + mode + "]");
+        }
+    }
+
+    private boolean checkLockNeedToWait() throws SemaphoreFailException {
         String threadName = Thread.currentThread().getName();
-        Timestamp lockTime = UtilDateTime.nowTimestamp();
         GenericValue semaphore;
 
         try {
@@ -59,43 +110,12 @@
 
             // use the special method below so we can reuse the unqiue tx functions
             dbWrite(semaphore, false);
-        } else {             
-            waitOrFail(mode);
-        }
-    }
-
-    public void release() throws SemaphoreFailException {
-        if (mode == SEMAPHORE_MODE_NONE) return;
-
-        // remove the lock file
-        dbWrite(lock, true);
-    }
-
-    private void waitOrFail(int mode) throws SemaphoreWaitException, SemaphoreFailException {
-        switch (mode) {
-            case SEMAPHORE_MODE_FAIL:
-                // fail
-                throw new SemaphoreFailException("Service [" + model.name + "] is locked");
-            case SEMAPHORE_MODE_WAIT:
-                if (wait < MAX_WAIT) {
-                    ++wait;
-                    try {
-                        Thread.sleep(SLEEP);               
-                    } catch (InterruptedException e) {
-                        Debug.logInfo(e, "Sleep interrupted: ServiceSemaphone.waitOrFail()", module);
-                    }
-
-                    // try again
-                    acquire();
-                    break;
-                } else {
-                    throw new SemaphoreWaitException("Service [" + model.name + "] wait timeout exceeded");
-                }
-            case SEMAPHORE_MODE_NONE:
-                Debug.logWarning("Semaphore mode [none] attempted to aquire a lock; but should not have!", module);
-                break;
-            default:
-                throw new SemaphoreFailException();
+            
+            // we own the lock, no waiting
+            return false;
+        } else {
+            // found a semaphore, need to wait
+            return true;
         }
     }