You are viewing a plain text version of this content. The canonical link for it is here.
Posted to ojb-dev@db.apache.org by ar...@apache.org on 2007/05/16 00:48:21 UTC

svn commit: r538351 - /db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/util/sequence/SequenceManagerInMemoryImpl.java

Author: arminw
Date: Tue May 15 15:48:20 2007
New Revision: 538351

URL: http://svn.apache.org/viewvc?view=rev&rev=538351
Log:
optimize performance for multithreaded environments

Modified:
    db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/util/sequence/SequenceManagerInMemoryImpl.java

Modified: db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/util/sequence/SequenceManagerInMemoryImpl.java
URL: http://svn.apache.org/viewvc/db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/util/sequence/SequenceManagerInMemoryImpl.java?view=diff&rev=538351&r1=538350&r2=538351
==============================================================================
--- db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/util/sequence/SequenceManagerInMemoryImpl.java (original)
+++ db/ojb/branches/OJB_1_0_RELEASE/src/java/org/apache/ojb/broker/util/sequence/SequenceManagerInMemoryImpl.java Tue May 15 15:48:20 2007
@@ -18,6 +18,7 @@
 import org.apache.ojb.broker.PersistenceBroker;
 import org.apache.ojb.broker.metadata.FieldDescriptor;
 import org.apache.ojb.broker.metadata.SequenceDescriptor;
+import org.apache.commons.lang.BooleanUtils;
 
 import java.util.HashMap;
 import java.util.Map;
@@ -64,6 +65,14 @@
  *    </td>
  * </tr>
  * <tr>
+ *     <td>seq.optimized</td>
+ *     <td>
+ *         If <tt>true</tt> the sequence manager use optimization for best performance in
+ *         multithreaded environments - continuous id numbers are not guaranteed. If <tt>false</tt>
+ *         this implementation use a simple counter for each sequence name (see autoNaming too).
+ *    </td>
+ * </tr>
+ * <tr>
  *     <td>autoNaming</td>
  *     <td>
  *          DEPRECATED. Default was 'true'. If set 'true' OJB try to build a
@@ -94,8 +103,14 @@
  */
 public class SequenceManagerInMemoryImpl extends AbstractSequenceManager
 {
+    public static final String PROPERTY_OPTIMIZED = "seq.optimized";
     protected static Map sequencesDBMap = new HashMap();
+    private static final int OFFSET = 20;
+    private static final Object LOCK = new Object();
+
     private long sequenceStart;
+    private Map localSequences = new HashMap();
+    private boolean optimized = true;
 
     /**
      * @deprecated
@@ -112,27 +127,55 @@
         super(broker, descriptor);
         Long start = SequenceManagerHelper.getSeqStart(getConfigurationProperties());
         sequenceStart = start != null ? start.longValue() : 1;
+        optimized = BooleanUtils.toBoolean(getConfigurationProperty(PROPERTY_OPTIMIZED, "true"));
     }
 
     protected long getUniqueLong(FieldDescriptor field) throws SequenceManagerException
     {
         String seqName = calculateSequenceName(field);
+        if(optimized)
+        {
+            LocalSequence seq = (LocalSequence) localSequences.get(seqName);
+            if(seq == null)
+            {
+                seq = new LocalSequence(0, 0);
+                localSequences.put(seqName, seq);
+            }
+            long result = seq.getNextId();
+            if(result == 0)
+            {
+                long newStart = prepareNextSequenceValue(field, seqName, OFFSET);
+                newStart -= OFFSET;
+                seq.refresh(newStart, OFFSET);
+                result = seq.getNextId();
+            }
+            //System.out.println("name=" +seqName + ", id=" + result);
+            return result;
+        }
+        else
+        {
+            //System.out.println("name=" +seqName + ", id=" + result);
+            return prepareNextSequenceValue(field, seqName, 1);
+        }
+    }
+
+    protected long prepareNextSequenceValue(FieldDescriptor field, String seqName, int offset)
+    {
         // we have to be threadsafe
-        synchronized (SequenceManagerInMemoryImpl.class)
+        synchronized (LOCK)
         {
             // get id for given seq name
-            Long currentId = getSequence(seqName);
+            GlobalValue current = getSequence(seqName);
             // check - first time we search for sequence name
-            if (currentId == null)
+            if (current == null)
             {
                 long maxKey = SequenceManagerHelper.getMaxForExtent(getBrokerForClass(), field);
                 maxKey = sequenceStart > maxKey ? sequenceStart : maxKey;
-                currentId = new Long(maxKey);
+                current = new GlobalValue(maxKey);
+                // put new seq to map
+                addSequence(seqName, current);
             }
-            currentId = new Long(currentId.longValue() + 1);
-            // put new id back to map
-            addSequence(seqName, currentId);
-            return currentId.intValue();
+            return current.next(offset);
         }
     }
 
@@ -143,15 +186,15 @@
      * @param sequenceName Name of the sequence.
      * @return Last used sequence value or <code>null</code>
      */
-    private Long getSequence(String sequenceName)
+    private GlobalValue getSequence(String sequenceName)
     {
-        Long result = null;
+        GlobalValue result = null;
         // now lookup the sequence map for calling DB
         Map mapForDB = (Map) sequencesDBMap.get(getBrokerForClass()
                 .serviceConnectionManager().getConnectionDescriptor().getJcdAlias());
         if(mapForDB != null)
         {
-            result = (Long) mapForDB.get(sequenceName);
+            result = (GlobalValue) mapForDB.get(sequenceName);
         }
         return result;
     }
@@ -161,7 +204,7 @@
      * @param sequenceName Name of the sequence.
      * @param seq The sequence value to add.
      */
-    private void addSequence(String sequenceName, Long seq)
+    private void addSequence(String sequenceName, GlobalValue seq)
     {
         // lookup the sequence map for calling DB
         String jcdAlias = getBrokerForClass()
@@ -202,5 +245,62 @@
     public void setSequenceStart(long sequenceStart)
     {
         this.sequenceStart = sequenceStart;
+    }
+
+    public boolean isOptimized()
+    {
+        return optimized;
+    }
+
+    public void setOptimized(boolean optimized)
+    {
+        this.optimized = optimized;
+    }
+
+    private static class LocalSequence
+    {
+        long startKey;
+        long maxKey;
+
+        public LocalSequence(long startKey, int offset)
+        {
+            refresh(startKey, offset);
+        }
+
+        long getNextId()
+        {
+            if (startKey == maxKey)
+            {
+                //no reserved IDs, must be reloaded, reserve new keyset and saved
+                return 0;
+            }
+            else
+            {
+                return ++startKey;
+            }
+        }
+
+        long refresh(long newStartKey, int offset)
+        {
+            startKey = newStartKey;
+            maxKey = newStartKey + offset;
+            return maxKey;
+        }
+    }
+
+    private static class GlobalValue
+    {
+        long current;
+
+        public GlobalValue(long current)
+        {
+            this.current = current;
+        }
+
+        long next(int offset)
+        {
+            current += offset;
+            return current;
+        }
     }
 }



---------------------------------------------------------------------
To unsubscribe, e-mail: ojb-dev-unsubscribe@db.apache.org
For additional commands, e-mail: ojb-dev-help@db.apache.org