svn commit: r1621335 - in /ofbiz/trunk/framework/entity/src/org/ofbiz/entity: test/EntityTestSuite.java util/SequenceUtil.java

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
1 message Options
Reply | Threaded
Open this post in threaded view
|

svn commit: r1621335 - in /ofbiz/trunk/framework/entity/src/org/ofbiz/entity: test/EntityTestSuite.java util/SequenceUtil.java

jacopoc
Author: jacopoc
Date: Fri Aug 29 16:26:51 2014
New Revision: 1621335

URL: http://svn.apache.org/r1621335
Log:
Fixed an issue affecting the thread safeness of the SequenceBank objects.
Added two unit tests to confirm the proper behavior of the SequenceUtil class; the second test fails without the fix committed with this revision.
Part of OFBIZ-2353.
This is just the first pass of my work to refactor the SequenceUtil.

Modified:
    ofbiz/trunk/framework/entity/src/org/ofbiz/entity/test/EntityTestSuite.java
    ofbiz/trunk/framework/entity/src/org/ofbiz/entity/util/SequenceUtil.java

Modified: ofbiz/trunk/framework/entity/src/org/ofbiz/entity/test/EntityTestSuite.java
URL: http://svn.apache.org/viewvc/ofbiz/trunk/framework/entity/src/org/ofbiz/entity/test/EntityTestSuite.java?rev=1621335&r1=1621334&r2=1621335&view=diff
==============================================================================
--- ofbiz/trunk/framework/entity/src/org/ofbiz/entity/test/EntityTestSuite.java (original)
+++ ofbiz/trunk/framework/entity/src/org/ofbiz/entity/test/EntityTestSuite.java Fri Aug 29 16:26:51 2014
@@ -27,9 +27,16 @@ import java.util.ArrayList;
 import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
+import java.util.UUID;
+import java.util.concurrent.Callable;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+import java.util.concurrent.Future;
+import java.util.concurrent.atomic.AtomicBoolean;
 
 import javax.sql.rowset.serial.SerialBlob;
 
+import org.ofbiz.base.concurrent.ExecutionPool;
 import org.ofbiz.base.util.Debug;
 import org.ofbiz.base.util.Observable;
 import org.ofbiz.base.util.Observer;
@@ -38,6 +45,7 @@ import org.ofbiz.base.util.UtilMisc;
 import org.ofbiz.base.util.UtilXml;
 import org.ofbiz.entity.Delegator;
 import org.ofbiz.entity.DelegatorFactory;
+import org.ofbiz.entity.GenericDelegator;
 import org.ofbiz.entity.GenericEntity;
 import org.ofbiz.entity.GenericEntityException;
 import org.ofbiz.entity.GenericPK;
@@ -56,6 +64,7 @@ import org.ofbiz.entity.transaction.Tran
 import org.ofbiz.entity.util.EntityFindOptions;
 import org.ofbiz.entity.util.EntityListIterator;
 import org.ofbiz.entity.util.EntitySaxReader;
+import org.ofbiz.entity.util.SequenceUtil;
 
 public class EntityTestSuite extends EntityTestCase {
 
@@ -1069,6 +1078,62 @@ public class EntityTestSuite extends Ent
         assertNull("Delete TestingType 2", testType);
     }
 
+    public void testSequenceValueItem() {
+        SequenceUtil sequencer = new SequenceUtil((GenericDelegator)delegator, delegator.getGroupHelperInfo(delegator.getEntityGroupName("SequenceValueItem")),
+                                                  delegator.getModelEntity("SequenceValueItem"),
+                                                  "seqName", "seqId");
+        UUID id = UUID.randomUUID();
+        String sequenceName = "BogusSequence" + id.toString();
+        for (int i = 10000; i <= 10015; i++) {
+            Long seqId = sequencer.getNextSeqId(sequenceName, 1, null);
+            assertEquals(seqId.longValue(), i);
+        }
+        sequencer.forceBankRefresh(sequenceName, 1);
+        Long seqId = sequencer.getNextSeqId(sequenceName, 1, null);
+        assertEquals(seqId.longValue(), 10020);
+    }
+
+    public void testSequenceValueItemWithConcurrentThreads() {
+        final SequenceUtil sequencer = new SequenceUtil((GenericDelegator)delegator, delegator.getGroupHelperInfo(delegator.getEntityGroupName("SequenceValueItem")),
+                                                  delegator.getModelEntity("SequenceValueItem"),
+                                                  "seqName", "seqId");
+        UUID id = UUID.randomUUID();
+        final String sequenceName = "BogusSequence" + id.toString();
+        final ConcurrentMap<Long, Long> seqIds = new ConcurrentHashMap<Long, Long>();
+        final AtomicBoolean duplicateFound = new AtomicBoolean(false);
+        final AtomicBoolean nullSeqIdReturned = new AtomicBoolean(false);
+
+        List<Future<Void>> futures = new ArrayList<Future<Void>>();
+        Callable getSeqIdTask = new Callable() {
+                    public Callable<Void> call() throws Exception {
+                        Long seqId = sequencer.getNextSeqId(sequenceName, 1, null);
+                        if (seqId == null) {
+                            nullSeqIdReturned.set(true);
+                            return null;
+                        }
+                        Long existingValue = seqIds.putIfAbsent(seqId, seqId);
+                        if (existingValue != null) {
+                            duplicateFound.set(true);
+                        }
+                        return null;
+                    }
+                };
+        Callable refreshTask = new Callable() {
+                            public Callable<Void> call() throws Exception {
+                                sequencer.forceBankRefresh(sequenceName, 1);
+                                return null;
+                            }
+                        };
+        double probabilityOfRefresh = 0.1;
+        for (int i = 1; i <= 1000; i++) {
+            Callable randomTask = Math.random() < probabilityOfRefresh ? refreshTask : getSeqIdTask;
+            futures.add(ExecutionPool.GLOBAL_FORK_JOIN.submit(randomTask));
+        }
+        ExecutionPool.getAllFutures(futures);
+        assertFalse("Null sequence id returned", nullSeqIdReturned.get());
+        assertFalse("Duplicate sequence id returned", duplicateFound.get());
+    }
+
     private final class TestObserver implements Observer {
         private Observable observable;
         private Object arg;

Modified: ofbiz/trunk/framework/entity/src/org/ofbiz/entity/util/SequenceUtil.java
URL: http://svn.apache.org/viewvc/ofbiz/trunk/framework/entity/src/org/ofbiz/entity/util/SequenceUtil.java?rev=1621335&r1=1621334&r2=1621335&view=diff
==============================================================================
--- ofbiz/trunk/framework/entity/src/org/ofbiz/entity/util/SequenceUtil.java (original)
+++ ofbiz/trunk/framework/entity/src/org/ofbiz/entity/util/SequenceUtil.java Fri Aug 29 16:26:51 2014
@@ -157,7 +157,7 @@ public class SequenceUtil {
             }
         }
 
-        private void refresh(long staggerMax) {
+        private synchronized void refresh(long staggerMax) {
             this.curSeqId = this.maxSeqId;
             this.fillBank(staggerMax);
         }