[jboss-cvs] JBoss Messaging SVN: r5049 - in trunk: tests/src/org/jboss/messaging/tests/unit/util and 1 other directory.

jboss-cvs-commits at lists.jboss.org jboss-cvs-commits at lists.jboss.org
Tue Sep 30 12:31:29 EDT 2008


Author: clebert.suconic at jboss.com
Date: 2008-09-30 12:31:29 -0400 (Tue, 30 Sep 2008)
New Revision: 5049

Modified:
   trunk/src/main/org/jboss/messaging/util/TimeAndCounterIDGenerator.java
   trunk/tests/src/org/jboss/messaging/tests/unit/util/TimeAndCounterIDGeneratorTest.java
Log:
ID Wrapping logic (throw an exception if the TimeIDGenerator capacity is overflowed)

Modified: trunk/src/main/org/jboss/messaging/util/TimeAndCounterIDGenerator.java
===================================================================
--- trunk/src/main/org/jboss/messaging/util/TimeAndCounterIDGenerator.java	2008-09-30 14:44:41 UTC (rev 5048)
+++ trunk/src/main/org/jboss/messaging/util/TimeAndCounterIDGenerator.java	2008-09-30 16:31:29 UTC (rev 5049)
@@ -27,11 +27,8 @@
 /**
  * A TimeAndCounterIDGenerator
  * <p>
- * Note: This sequence generator is valid as long as you generate less than 268435455 (fffffff) IDs per 250 millisecond
+ * This IDGenerator doesn't support more than 268435455 IDs per 250 millisecond. It would throw an exception if this happens.
  * </p>
- * <p>
- * (what is impossible at this point, This class alone will probably take a few seconds to generate this many IDs)
- * </p>
  * 
  * @author <a href="mailto:clebert.suconic at jboss.org">Clebert Suconic</a>
  * @author <a href="mailto:tim.fox at jboss.com">Tim Fox</a> Created Sep 24, 2008 11:54:10 AM
@@ -45,8 +42,12 @@
     */
    private static final int BITS_TO_MOVE = 20;
 
-   public static final long MASK_TIME = 0xEFFFFFFFF00l;
+   public static final long MASK_TIME = 0xeffffffff00l;
 
+   public static final long ID_MASK = 0xfffffffl;
+
+   private static final long TIME_ID_MASK = 0xeffffffff0000000l;
+
    // Attributes ----------------------------------------------------
 
    private final AtomicLong counter = new AtomicLong(0);
@@ -68,7 +69,33 @@
 
    public long generateID()
    {
-      return counter.incrementAndGet();
+      long idReturn = counter.incrementAndGet();
+
+      if ((idReturn & ID_MASK) == ID_MASK)
+      {
+         final long timePortion = (idReturn & TIME_ID_MASK); 
+         
+         // Wrapping ID logic
+
+         if (timePortion > newTM())
+         {
+            // Unlikely too happen
+            
+            // This will only happen if a computer can generate more than ID_MASK ids (268.43 million IDs per 250 milliseconds)
+            // If this wrapping code starts to happen too often, it needs revision as we need to wait until the time component is updated
+            throw new IllegalStateException("The IDGenerator is being overlaped, and it needs revision as the system generated more than " + (idReturn & ID_MASK) +
+                     " ids per 250 milliseconds which exceeded the IDgenerator limit");
+         }
+         else
+         {
+            // Else.. no worry... we will just accept the new time portion being added
+            // This time-mark would have been generated some time ago, so this is ok.
+            // tmMark is just a cache to validate the MaxIDs, so there is no need to 
+            tmMark = timePortion;
+         }
+      }
+
+      return idReturn;
    }
 
    public long getCurrentID()
@@ -94,7 +121,7 @@
       long oldTm = tmMark;
       long newTm = newTM();
 
-      while (newTm == oldTm)
+      while (newTm <= oldTm)
       {
          newTm = newTM();
       }

Modified: trunk/tests/src/org/jboss/messaging/tests/unit/util/TimeAndCounterIDGeneratorTest.java
===================================================================
--- trunk/tests/src/org/jboss/messaging/tests/unit/util/TimeAndCounterIDGeneratorTest.java	2008-09-30 14:44:41 UTC (rev 5048)
+++ trunk/tests/src/org/jboss/messaging/tests/unit/util/TimeAndCounterIDGeneratorTest.java	2008-09-30 16:31:29 UTC (rev 5049)
@@ -160,7 +160,38 @@
       hashSet.clear();
 
    }
+   
+   public void testWrapID() throws Throwable
+   {
+      final ConcurrentHashSet<Long> hashSet = new ConcurrentHashSet<Long>();
 
+      final TimeAndCounterIDGenerator seq = new TimeAndCounterIDGenerator();
+
+      System.out.println("Current Time = " + hex(System.currentTimeMillis()));
+      
+      seq.setInternalDate(System.currentTimeMillis() + 10000l); // 10 seconds in the future
+
+      seq.setInternalID(TimeAndCounterIDGenerator.ID_MASK -1); // 1 ID about to explode
+     
+      try
+      {
+         // This is simulating a situation where we generated more than 268 million messages on the same time interval
+         seq.generateID();
+         fail("It was supposed to throw an exception, as the counter was set to explode on this test");
+      }
+      catch (Exception e)
+      {
+      }
+
+      
+      seq.setInternalDate(System.currentTimeMillis() - 10000l); // 10 seconds in the past
+
+      seq.setInternalID(TimeAndCounterIDGenerator.ID_MASK -1); // 1 ID about to explode
+      
+      // This is ok... the time portion would be added to the next one generated 10 seconds ago
+      seq.generateID();
+   }
+
    private static String hex(final long value)
    {
       return String.format("%1$X", value);




More information about the jboss-cvs-commits mailing list