You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ofbiz.apache.org by ja...@apache.org on 2007/09/12 22:58:45 UTC
svn commit: r575074 - in /ofbiz/trunk/framework/service: dtd/ entitydef/
src/org/ofbiz/service/ src/org/ofbiz/service/semaphore/
Author: jaz
Date: Wed Sep 12 13:58:44 2007
New Revision: 575074
URL: http://svn.apache.org/viewvc?rev=575074&view=rev
Log:
implemented ServiceSemaphore; built in locking to prevent services (when defined) from running at the same time; uses database record to work with a cluser of application servers. Three modes are available:
None - Does no locking
Wait - Waits for the previous service to complete (currently up to 5 minutes)
Fail - Fails when the same service is already running
use the semaphore="none|wait|fail" in the service definition (none is the default when the attribute is not defined)
Added:
ofbiz/trunk/framework/service/src/org/ofbiz/service/semaphore/
ofbiz/trunk/framework/service/src/org/ofbiz/service/semaphore/SemaphoreFailException.java (with props)
ofbiz/trunk/framework/service/src/org/ofbiz/service/semaphore/SemaphoreWaitException.java (with props)
ofbiz/trunk/framework/service/src/org/ofbiz/service/semaphore/ServiceSemaphore.java (with props)
Modified:
ofbiz/trunk/framework/service/dtd/services.xsd
ofbiz/trunk/framework/service/entitydef/entitygroup.xml
ofbiz/trunk/framework/service/entitydef/entitymodel.xml
ofbiz/trunk/framework/service/src/org/ofbiz/service/ModelService.java
ofbiz/trunk/framework/service/src/org/ofbiz/service/ModelServiceReader.java
ofbiz/trunk/framework/service/src/org/ofbiz/service/ServiceDispatcher.java
Modified: ofbiz/trunk/framework/service/dtd/services.xsd
URL: http://svn.apache.org/viewvc/ofbiz/trunk/framework/service/dtd/services.xsd?rev=575074&r1=575073&r2=575074&view=diff
==============================================================================
--- ofbiz/trunk/framework/service/dtd/services.xsd (original)
+++ ofbiz/trunk/framework/service/dtd/services.xsd Wed Sep 12 13:58:44 2007
@@ -111,6 +111,15 @@
</xs:restriction>
</xs:simpleType>
</xs:attribute>
+ <xs:attribute name="semaphore" default="none">
+ <xs:simpleType>
+ <xs:restriction base="xs:token">
+ <xs:enumeration value="none"/>
+ <xs:enumeration value="fail"/>
+ <xs:enumeration value="wait"/>
+ </xs:restriction>
+ </xs:simpleType>
+ </xs:attribute>
</xs:attributeGroup>
<xs:element name="notification">
<xs:complexType>
Modified: ofbiz/trunk/framework/service/entitydef/entitygroup.xml
URL: http://svn.apache.org/viewvc/ofbiz/trunk/framework/service/entitydef/entitygroup.xml?rev=575074&r1=575073&r2=575074&view=diff
==============================================================================
--- ofbiz/trunk/framework/service/entitydef/entitygroup.xml (original)
+++ ofbiz/trunk/framework/service/entitydef/entitygroup.xml Wed Sep 12 13:58:44 2007
@@ -29,5 +29,10 @@
<entity-group group="org.ofbiz" entity="RecurrenceInfo" />
<entity-group group="org.ofbiz" entity="RecurrenceRule" />
<entity-group group="org.ofbiz" entity="RuntimeData" />
+
+ <!-- ========================================================= -->
+ <!-- org.ofbiz.service.semaphore -->
+ <!-- ========================================================= -->
+ <entity-group group="org.ofbiz" entity="ServiceSemaphore" />
</entitygroup>
Modified: ofbiz/trunk/framework/service/entitydef/entitymodel.xml
URL: http://svn.apache.org/viewvc/ofbiz/trunk/framework/service/entitydef/entitymodel.xml?rev=575074&r1=575073&r2=575074&view=diff
==============================================================================
--- ofbiz/trunk/framework/service/entitydef/entitymodel.xml (original)
+++ ofbiz/trunk/framework/service/entitydef/entitymodel.xml Wed Sep 12 13:58:44 2007
@@ -33,6 +33,7 @@
<!-- ======================== Data Model ===================== -->
<!-- The modules in this file are as follows: -->
<!-- - org.ofbiz.service.schedule -->
+ <!-- - org.ofbiz.service.semaphore -->
<!-- ========================================================= -->
@@ -41,7 +42,7 @@
<!-- ========================================================= -->
<entity entity-name="JobSandbox" package-name="org.ofbiz.service.schedule" title="Job Scheduler Sandbox Entity"
- sequence-bank-size="100">
+ sequence-bank-size="100">
<field name="jobId" type="id-ne"></field>
<field name="jobName" type="name"></field>
<field name="runTime" type="date-time"></field>
@@ -121,9 +122,21 @@
<prim-key field="recurrenceRuleId"/>
</entity>
<entity entity-name="RuntimeData" package-name="org.ofbiz.service.schedule" title="Runtime Data Entity"
- sequence-bank-size="100">
+ sequence-bank-size="100">
<field name="runtimeDataId" type="id-ne"></field>
<field name="runtimeInfo" type="very-long"></field>
<prim-key field="runtimeDataId"/>
</entity>
+
+ <!-- ========================================================= -->
+ <!-- org.ofbiz.service.semaphore -->
+ <!-- ========================================================= -->
+ <entity entity-name="ServiceSemaphore" package-name="org.ofbiz.service.semaphore" title="Semaphore Lock Entity"
+ sequence-bank-size="100">
+ <field name="serviceName" type="name"></field>
+ <field name="lockThread" type="name"></field>
+ <field name="lockTime" type="date-time"></field>
+ <prim-key field="serviceName"/>
+ </entity>
+
</entitymodel>
Modified: ofbiz/trunk/framework/service/src/org/ofbiz/service/ModelService.java
URL: http://svn.apache.org/viewvc/ofbiz/trunk/framework/service/src/org/ofbiz/service/ModelService.java?rev=575074&r1=575073&r2=575074&view=diff
==============================================================================
--- ofbiz/trunk/framework/service/src/org/ofbiz/service/ModelService.java (original)
+++ ofbiz/trunk/framework/service/src/org/ofbiz/service/ModelService.java Wed Sep 12 13:58:44 2007
@@ -133,6 +133,9 @@
/** Permission service resource-description */
public String permissionResourceDesc;
+
+ /** Semaphore setting (wait, fail, none) */
+ public String semaphore;
/** Set of services this service implements */
public Set implServices = new ListOrderedSet();
Modified: ofbiz/trunk/framework/service/src/org/ofbiz/service/ModelServiceReader.java
URL: http://svn.apache.org/viewvc/ofbiz/trunk/framework/service/src/org/ofbiz/service/ModelServiceReader.java?rev=575074&r1=575073&r2=575074&view=diff
==============================================================================
--- ofbiz/trunk/framework/service/src/org/ofbiz/service/ModelServiceReader.java (original)
+++ ofbiz/trunk/framework/service/src/org/ofbiz/service/ModelServiceReader.java Wed Sep 12 13:58:44 2007
@@ -258,7 +258,8 @@
service.name = UtilXml.checkEmpty(serviceElement.getAttribute("name"));
service.engineName = UtilXml.checkEmpty(serviceElement.getAttribute("engine"));
service.location = UtilXml.checkEmpty(serviceElement.getAttribute("location"));
- service.invoke = UtilXml.checkEmpty(serviceElement.getAttribute("invoke"));
+ service.invoke = UtilXml.checkEmpty(serviceElement.getAttribute("invoke"));
+ service.semaphore = UtilXml.checkEmpty(serviceElement.getAttribute("semaphore"));
service.defaultEntityName = UtilXml.checkEmpty(serviceElement.getAttribute("default-entity-name"));
service.fromLoader = isFromURL ? readerURL.toExternalForm() : handler.getLoaderName();
Modified: ofbiz/trunk/framework/service/src/org/ofbiz/service/ServiceDispatcher.java
URL: http://svn.apache.org/viewvc/ofbiz/trunk/framework/service/src/org/ofbiz/service/ServiceDispatcher.java?rev=575074&r1=575073&r2=575074&view=diff
==============================================================================
--- ofbiz/trunk/framework/service/src/org/ofbiz/service/ServiceDispatcher.java (original)
+++ ofbiz/trunk/framework/service/src/org/ofbiz/service/ServiceDispatcher.java Wed Sep 12 13:58:44 2007
@@ -18,24 +18,11 @@
*******************************************************************************/
package org.ofbiz.service;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Locale;
-import java.util.Map;
-
-import javax.transaction.Transaction;
-
import javolution.util.FastList;
import javolution.util.FastMap;
-
import org.apache.commons.collections.map.LRUMap;
import org.ofbiz.base.config.GenericConfigException;
-import org.ofbiz.base.util.Debug;
-import org.ofbiz.base.util.GeneralRuntimeException;
-import org.ofbiz.base.util.UtilMisc;
-import org.ofbiz.base.util.UtilTimer;
-import org.ofbiz.base.util.UtilValidate;
-import org.ofbiz.base.util.UtilXml;
+import org.ofbiz.base.util.*;
import org.ofbiz.entity.GenericDelegator;
import org.ofbiz.entity.GenericEntityException;
import org.ofbiz.entity.GenericValue;
@@ -53,8 +40,15 @@
import org.ofbiz.service.jms.JmsListenerFactory;
import org.ofbiz.service.job.JobManager;
import org.ofbiz.service.job.JobManagerException;
+import org.ofbiz.service.semaphore.ServiceSemaphore;
import org.w3c.dom.Element;
+import javax.transaction.Transaction;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+
/**
* Global Service Dispatcher
*/
@@ -237,6 +231,13 @@
* @throws GenericServiceException
*/
public Map runSync(String localName, ModelService modelService, Map context, boolean validateOut) throws ServiceAuthException, ServiceValidationException, GenericServiceException {
+ // check for semaphore and aquire a lock
+ ServiceSemaphore lock = null;
+ if ("wait".equals(modelService.semaphore) || "fail".equals(modelService.semaphore)) {
+ lock = new ServiceSemaphore(delegator, modelService);
+ lock.acquire();
+ }
+
long serviceStartTime = System.currentTimeMillis();
boolean debugging = checkDebug(modelService, 1, true);
if (Debug.verboseOn()) {
@@ -540,6 +541,11 @@
Debug.logTiming("Sync service [" + localName + "/" + modelService.name + "] finished in [" + timeToRun + "] milliseconds", module);
} else if (timeToRun > 200) {
Debug.logInfo("Sync service [" + localName + "/" + modelService.name + "] finished in [" + timeToRun + "] milliseconds", module);
+ }
+
+ // release the semaphore lock
+ if (lock != null) {
+ lock.release();
}
return result;
Added: ofbiz/trunk/framework/service/src/org/ofbiz/service/semaphore/SemaphoreFailException.java
URL: http://svn.apache.org/viewvc/ofbiz/trunk/framework/service/src/org/ofbiz/service/semaphore/SemaphoreFailException.java?rev=575074&view=auto
==============================================================================
--- ofbiz/trunk/framework/service/src/org/ofbiz/service/semaphore/SemaphoreFailException.java (added)
+++ ofbiz/trunk/framework/service/src/org/ofbiz/service/semaphore/SemaphoreFailException.java Wed Sep 12 13:58:44 2007
@@ -0,0 +1,25 @@
+package org.ofbiz.service.semaphore;
+
+import org.ofbiz.service.GenericServiceException;
+
+/**
+ * SemaphoreFailException
+ */
+public class SemaphoreFailException extends GenericServiceException {
+
+ public SemaphoreFailException() {
+ super();
+ }
+
+ public SemaphoreFailException(String str) {
+ super(str);
+ }
+
+ public SemaphoreFailException(String str, Throwable nested) {
+ super(str, nested);
+ }
+
+ public SemaphoreFailException(Throwable nested) {
+ super(nested);
+ }
+}
Propchange: ofbiz/trunk/framework/service/src/org/ofbiz/service/semaphore/SemaphoreFailException.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: ofbiz/trunk/framework/service/src/org/ofbiz/service/semaphore/SemaphoreFailException.java
------------------------------------------------------------------------------
svn:keywords = "Date Rev Author URL Id"
Propchange: ofbiz/trunk/framework/service/src/org/ofbiz/service/semaphore/SemaphoreFailException.java
------------------------------------------------------------------------------
svn:mime-type = text/plain
Added: ofbiz/trunk/framework/service/src/org/ofbiz/service/semaphore/SemaphoreWaitException.java
URL: http://svn.apache.org/viewvc/ofbiz/trunk/framework/service/src/org/ofbiz/service/semaphore/SemaphoreWaitException.java?rev=575074&view=auto
==============================================================================
--- ofbiz/trunk/framework/service/src/org/ofbiz/service/semaphore/SemaphoreWaitException.java (added)
+++ ofbiz/trunk/framework/service/src/org/ofbiz/service/semaphore/SemaphoreWaitException.java Wed Sep 12 13:58:44 2007
@@ -0,0 +1,25 @@
+package org.ofbiz.service.semaphore;
+
+import org.ofbiz.service.GenericServiceException;
+
+/**
+ * SemaphoreWaitException
+ */
+public class SemaphoreWaitException extends GenericServiceException {
+
+ public SemaphoreWaitException() {
+ super();
+ }
+
+ public SemaphoreWaitException(String str) {
+ super(str);
+ }
+
+ public SemaphoreWaitException(String str, Throwable nested) {
+ super(str, nested);
+ }
+
+ public SemaphoreWaitException(Throwable nested) {
+ super(nested);
+ }
+}
Propchange: ofbiz/trunk/framework/service/src/org/ofbiz/service/semaphore/SemaphoreWaitException.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: ofbiz/trunk/framework/service/src/org/ofbiz/service/semaphore/SemaphoreWaitException.java
------------------------------------------------------------------------------
svn:keywords = "Date Rev Author URL Id"
Propchange: ofbiz/trunk/framework/service/src/org/ofbiz/service/semaphore/SemaphoreWaitException.java
------------------------------------------------------------------------------
svn:mime-type = text/plain
Added: 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=575074&view=auto
==============================================================================
--- ofbiz/trunk/framework/service/src/org/ofbiz/service/semaphore/ServiceSemaphore.java (added)
+++ ofbiz/trunk/framework/service/src/org/ofbiz/service/semaphore/ServiceSemaphore.java Wed Sep 12 13:58:44 2007
@@ -0,0 +1,155 @@
+package org.ofbiz.service.semaphore;
+
+import org.ofbiz.base.util.Debug;
+import org.ofbiz.base.util.UtilDateTime;
+import org.ofbiz.base.util.UtilMisc;
+import org.ofbiz.entity.GenericDelegator;
+import org.ofbiz.entity.GenericEntityException;
+import org.ofbiz.entity.GenericValue;
+import org.ofbiz.entity.transaction.GenericTransactionException;
+import org.ofbiz.entity.transaction.TransactionUtil;
+import org.ofbiz.service.ModelService;
+
+import javax.transaction.Transaction;
+import java.sql.Timestamp;
+import java.util.Map;
+
+/**
+ * ServiceSemaphore
+ */
+public class ServiceSemaphore {
+
+ public static final String module = ServiceSemaphore.class.getName();
+ public static final int SEMAPHORE_MODE_FAIL = 0;
+ public static final int SEMAPHORE_MODE_WAIT = 1;
+ public static final int SEMAPHORE_MODE_NONE = 2;
+ public static final long MAX_WAIT = 600;
+ public static final long SLEEP = 500;
+
+ protected GenericDelegator delegator;
+ protected GenericValue lock;
+ protected ModelService model;
+
+ protected int wait = 0;
+ protected int mode = 2;
+
+ public ServiceSemaphore(GenericDelegator delegator, ModelService model) {
+ this.mode = "wait".equals(model.semaphore) ? 1 : ("fail".equals(model.semaphore) ? 0 : 2);
+ this.delegator = delegator;
+ this.model = model;
+ this.lock = null;
+ }
+
+ public void acquire() throws SemaphoreWaitException, SemaphoreFailException {
+ if (mode == SEMAPHORE_MODE_NONE) return;
+
+ String threadName = Thread.currentThread().getName();
+ Timestamp lockTime = UtilDateTime.nowTimestamp();
+ GenericValue semaphore;
+
+ try {
+ semaphore = delegator.findByPrimaryKey("ServiceSemaphore", UtilMisc.toMap("serviceName", model.name));
+ } catch (GenericEntityException e) {
+ throw new SemaphoreFailException(e);
+ }
+
+ if (semaphore == null) {
+ Map fields = UtilMisc.toMap("serviceName", model.name, "lockThread", threadName, "lockTime", lockTime);
+ semaphore = delegator.makeValue("ServiceSemaphore", fields);
+
+ // 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();
+ }
+ }
+
+ private synchronized void dbWrite(GenericValue value, boolean delete) throws SemaphoreFailException {
+ Transaction parent = null;
+ boolean beganTx = false;
+ boolean isError = false;
+
+ try {
+ // prepare the suspended transaction
+ parent = TransactionUtil.suspend();
+ beganTx = TransactionUtil.begin();
+ if (!beganTx) {
+ throw new SemaphoreFailException("Cannot obtain unique transaction for semaphore logging");
+ }
+
+ // store the value
+ try {
+ if (delete) {
+ value.refresh();
+ value.remove();
+ lock = null;
+ } else {
+ lock = value.create();
+ }
+ } catch (GenericEntityException e) {
+ Debug.logError(e, module);
+ isError = true;
+ throw new SemaphoreFailException("Cannot obtain unique transaction for semaphore logging");
+ }
+ } catch (GenericTransactionException e) {
+ Debug.logError(e, module);
+ } finally {
+ if (isError) {
+ try {
+ TransactionUtil.rollback(beganTx, "ServiceSemaphore: dbWrite()", new Exception());
+ } catch (GenericTransactionException e) {
+ Debug.logError(e, module);
+ }
+ }
+ if (!isError && beganTx) {
+ try {
+ TransactionUtil.commit(beganTx);
+ } catch (GenericTransactionException e) {
+ Debug.logError(e, module);
+ }
+ }
+ if (parent != null) {
+ try {
+ TransactionUtil.resume(parent);
+ } catch (GenericTransactionException e) {
+ Debug.logError(e, module);
+ }
+ }
+ }
+ }
+}
Propchange: ofbiz/trunk/framework/service/src/org/ofbiz/service/semaphore/ServiceSemaphore.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: ofbiz/trunk/framework/service/src/org/ofbiz/service/semaphore/ServiceSemaphore.java
------------------------------------------------------------------------------
svn:keywords = "Date Rev Author URL Id"
Propchange: ofbiz/trunk/framework/service/src/org/ofbiz/service/semaphore/ServiceSemaphore.java
------------------------------------------------------------------------------
svn:mime-type = text/plain