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


Reply via email to