[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