[jboss-cvs] JBoss Messaging SVN: r3371 - in branches/Branch_Stable: src/main/org/jboss/jms/client/remoting and 4 other directories.
jboss-cvs-commits at lists.jboss.org
jboss-cvs-commits at lists.jboss.org
Tue Nov 27 14:43:02 EST 2007
Author: timfox
Date: 2007-11-27 14:43:01 -0500 (Tue, 27 Nov 2007)
New Revision: 3371
Added:
branches/Branch_Stable/src/main/org/jboss/messaging/util/Reorderer.java
branches/Branch_Stable/tests/src/org/jboss/test/messaging/util/ReordererTest.java
Modified:
branches/Branch_Stable/src/main/org/jboss/jms/client/container/ClientConsumer.java
branches/Branch_Stable/src/main/org/jboss/jms/client/container/ConsumerAspect.java
branches/Branch_Stable/src/main/org/jboss/jms/client/remoting/CallbackManager.java
branches/Branch_Stable/src/main/org/jboss/jms/client/state/SessionState.java
branches/Branch_Stable/src/main/org/jboss/jms/server/endpoint/ServerSessionEndpoint.java
Log:
http://jira.jboss.org/jira/browse/JBMESSAGING-1166
Modified: branches/Branch_Stable/src/main/org/jboss/jms/client/container/ClientConsumer.java
===================================================================
--- branches/Branch_Stable/src/main/org/jboss/jms/client/container/ClientConsumer.java 2007-11-27 13:19:26 UTC (rev 3370)
+++ branches/Branch_Stable/src/main/org/jboss/jms/client/container/ClientConsumer.java 2007-11-27 19:43:01 UTC (rev 3371)
@@ -35,10 +35,13 @@
import org.jboss.jms.delegate.DefaultCancel;
import org.jboss.jms.delegate.DeliveryInfo;
import org.jboss.jms.delegate.SessionDelegate;
+import org.jboss.jms.message.JBossMessage;
import org.jboss.jms.message.MessageProxy;
+import org.jboss.jms.wireformat.ClientDelivery;
import org.jboss.logging.Logger;
import org.jboss.messaging.core.contract.Message;
import org.jboss.messaging.util.Future;
+import org.jboss.messaging.util.Reorderer;
import org.jboss.messaging.util.prioritylinkedlist.BasicPriorityLinkedList;
import org.jboss.messaging.util.prioritylinkedlist.PriorityLinkedList;
@@ -216,7 +219,8 @@
private boolean handleFlowControl;
private long redeliveryDelay;
private volatile int currentToken;
-
+ private Reorderer reorderer;
+
// Constructors ---------------------------------------------------------------------------------
public ClientConsumer(boolean isCC, int ackMode,
@@ -224,7 +228,7 @@
String queueName,
int bufferSize, QueuedExecutor sessionExecutor,
int maxDeliveries, boolean shouldAck, boolean handleFlowControl,
- long redeliveryDelay)
+ long redeliveryDelay, Reorderer reorderer)
{
if (bufferSize < 1)
{
@@ -246,11 +250,14 @@
this.shouldAck = shouldAck;
this.handleFlowControl = handleFlowControl;
this.redeliveryDelay = redeliveryDelay;
+ this.reorderer = reorderer;
}
// Public ---------------------------------------------------------------------------------------
+
+
public boolean isClosed()
{
return closed;
@@ -263,12 +270,24 @@
*/
public void handleMessage(final Object message) throws Exception
{
+ ClientDelivery del = (ClientDelivery)message;
+
+ //We need to make sure the deliveries are in the right order -
+ //Due to the way remoting pooling works we cannot guarantee invocations will use the same TCP connection
+ //Therefore they can be delivered out of order.
+ //We therefore need to re-order them on arrival
+
+ Message msg = del.getMessage();
+
+ MessageProxy proxy = JBossMessage.
+ createThinDelegate(del.getDeliveryId(), (JBossMessage)msg, del.getDeliveryCount());
+
//TODO - we temporarily need to execute on a different thread to avoid a deadlock situation in
// failover where a message is sent then the valve is locked, and the message send cause
// a message delivery back to the same client which tries to ack but can't get through
// the valve. This won't be necessary when we move to a non blocking transport
-
- sessionExecutor.execute(new HandleMessageRunnable(currentToken, message));
+
+ reorderer.handle(new HandleMessageRunnable(currentToken, proxy), del.getDeliveryId());
}
public void setMessageListener(MessageListener listener) throws JMSException
@@ -860,21 +879,19 @@
{
private int token;
- private Object message;
+ private MessageProxy proxy;
- HandleMessageRunnable(int token, Object message)
+ HandleMessageRunnable(int token, MessageProxy proxy)
{
this.token = token;
- this.message = message;
+ this.proxy = proxy;
}
public void run()
{
try
{
- MessageProxy proxy = (MessageProxy) message;
-
if (trace) { log.trace(this + " receiving message " + proxy + " from the remoting layer"); }
synchronized (mainLock)
@@ -889,7 +906,7 @@
if (token != currentToken)
{
//This message was queued up from before failover - we don't want to add it
- log.trace("Ignoring message " + message);
+ log.trace("Ignoring message " + proxy);
return;
}
@@ -1000,7 +1017,7 @@
if (trace) { log.trace("Exiting run()"); }
}
- }
+ }
}
Modified: branches/Branch_Stable/src/main/org/jboss/jms/client/container/ConsumerAspect.java
===================================================================
--- branches/Branch_Stable/src/main/org/jboss/jms/client/container/ConsumerAspect.java 2007-11-27 13:19:26 UTC (rev 3370)
+++ branches/Branch_Stable/src/main/org/jboss/jms/client/container/ConsumerAspect.java 2007-11-27 19:43:01 UTC (rev 3371)
@@ -36,6 +36,7 @@
import org.jboss.jms.exception.MessagingShutdownException;
import org.jboss.logging.Logger;
import org.jboss.messaging.util.MessageQueueNameHelper;
+import org.jboss.messaging.util.Reorderer;
import EDU.oswego.cs.dl.util.concurrent.QueuedExecutor;
@@ -83,6 +84,7 @@
String consumerID = consumerState.getConsumerID();
int prefetchSize = consumerState.getBufferSize();
QueuedExecutor sessionExecutor = sessionState.getExecutor();
+ Reorderer reorderer = sessionState.getReorderer();
int maxDeliveries = consumerState.getMaxDeliveries();
long redeliveryDelay = consumerState.getRedeliveryDelay();
@@ -110,7 +112,7 @@
new ClientConsumer(isCC, sessionState.getAcknowledgeMode(),
sessionDelegate, consumerDelegate, consumerID, queueName,
prefetchSize, sessionExecutor, maxDeliveries, consumerState.isShouldAck(),
- autoFlowControl, redeliveryDelay);
+ autoFlowControl, redeliveryDelay, reorderer);
sessionState.addCallbackHandler(messageHandler);
Modified: branches/Branch_Stable/src/main/org/jboss/jms/client/remoting/CallbackManager.java
===================================================================
--- branches/Branch_Stable/src/main/org/jboss/jms/client/remoting/CallbackManager.java 2007-11-27 13:19:26 UTC (rev 3370)
+++ branches/Branch_Stable/src/main/org/jboss/jms/client/remoting/CallbackManager.java 2007-11-27 19:43:01 UTC (rev 3371)
@@ -84,11 +84,6 @@
{
ClientDelivery dr = (ClientDelivery)parameter;
- Message msg = dr.getMessage();
-
- MessageProxy proxy = JBossMessage.
- createThinDelegate(dr.getDeliveryId(), (JBossMessage)msg, dr.getDeliveryCount());
-
ClientConsumer handler =
(ClientConsumer)callbackHandlers.get(dr.getConsumerId());
@@ -102,7 +97,7 @@
try
{
- handler.handleMessage(proxy);
+ handler.handleMessage(dr);
}
catch (Exception e)
{
Modified: branches/Branch_Stable/src/main/org/jboss/jms/client/state/SessionState.java
===================================================================
--- branches/Branch_Stable/src/main/org/jboss/jms/client/state/SessionState.java 2007-11-27 13:19:26 UTC (rev 3370)
+++ branches/Branch_Stable/src/main/org/jboss/jms/client/state/SessionState.java 2007-11-27 19:43:01 UTC (rev 3371)
@@ -47,6 +47,7 @@
import org.jboss.jms.tx.ResourceManager;
import org.jboss.logging.Logger;
import org.jboss.messaging.util.ClearableQueuedExecutor;
+import org.jboss.messaging.util.Reorderer;
import org.jboss.messaging.util.Version;
import EDU.oswego.cs.dl.util.concurrent.LinkedQueue;
@@ -111,6 +112,8 @@
private long npSendSequence;
+ private Reorderer reorderer;
+
// Constructors ---------------------------------------------------------------------------------
public SessionState(ConnectionState parent, ClientSessionDelegate delegate,
@@ -150,6 +153,8 @@
// TODO could optimise this to use the same map of callbackmanagers (which holds refs
// to callbackhandlers) in the connection, instead of maintaining another map
callbackHandlers = new HashMap();
+
+ this.reorderer = new ReceiveReorderer();
}
// HierarchicalState implementation -------------------------------------------------------------
@@ -344,20 +349,26 @@
del.getMessageProxy().getMessage().getMessageID(),
del.getQueueName());
- recoveryInfos.add(recInfo);
+ recoveryInfos.add(recInfo);
}
}
-
- //Note! We ALWAYS call recoverDeliveries even if there are no deliveries since it also does other stuff
- //like remove from recovery Area refs corresponding to messages in client consumer buffers
log.trace(this + " sending delivery recovery " + recoveryInfos + " on failover");
//Note we only recover sessions that are transacted or client ack
if (transacted || xa || acknowledgeMode == Session.CLIENT_ACKNOWLEDGE)
{
+ //Note! We ALWAYS call recoverDeliveries even if there are no deliveries since it also does other stuff
+ //like remove from recovery Area refs corresponding to messages in client consumer buffers
+
newDelegate.recoverDeliveries(recoveryInfos, oldSessionID);
}
+ else
+ {
+ //The delivery id will get reset so we must reset on the re-orderer too
+
+ reorderer.reset();
+ }
}
// Public ---------------------------------------------------------------------------------------
@@ -475,6 +486,11 @@
npSendSequence++;
}
+ public Reorderer getReorderer()
+ {
+ return reorderer;
+ }
+
public String toString()
{
return "SessionState[" + sessionID + "]";
@@ -487,6 +503,14 @@
// Private --------------------------------------------------------------------------------------
// Inner classes --------------------------------------------------------------------------------
+
+ private class ReceiveReorderer extends Reorderer
+ {
+ public void execute(Object object) throws Exception
+ {
+ executor.execute((Runnable)object);
+ }
+ }
}
Modified: branches/Branch_Stable/src/main/org/jboss/jms/server/endpoint/ServerSessionEndpoint.java
===================================================================
--- branches/Branch_Stable/src/main/org/jboss/jms/server/endpoint/ServerSessionEndpoint.java 2007-11-27 13:19:26 UTC (rev 3370)
+++ branches/Branch_Stable/src/main/org/jboss/jms/server/endpoint/ServerSessionEndpoint.java 2007-11-27 19:43:01 UTC (rev 3371)
@@ -86,6 +86,7 @@
import org.jboss.messaging.util.ExceptionUtil;
import org.jboss.messaging.util.GUIDGenerator;
import org.jboss.messaging.util.MessageQueueNameHelper;
+import org.jboss.messaging.util.Reorderer;
import org.jboss.remoting.Client;
import org.jboss.remoting.callback.Callback;
import org.jboss.remoting.callback.ServerInvokerCallbackHandler;
@@ -128,8 +129,6 @@
private static final long DELIVERY_WAIT_TIMEOUT = 5 * 1000;
- private static final long CLOSE_WAIT_TIMEOUT = 5 * 1000;
-
// Static ---------------------------------------------------------------------------------------
// Attributes -----------------------------------------------------------------------------------
@@ -168,17 +167,17 @@
// Map <deliveryID, Delivery>
private Map deliveries;
- private SynchronizedLong deliveryIdSequence;
+ private long deliveryIdSequence;
//Temporary until we have our own NIO transport
QueuedExecutor executor = new QueuedExecutor(new LinkedQueue());
private LinkedQueue toDeliver = new LinkedQueue();
+ private Reorderer reorderer = new SendReorderer();
+
private boolean waitingToClose = false;
- private Object waitLock = new Object();
-
// Constructors ---------------------------------------------------------------------------------
ServerSessionEndpoint(String sessionID, ServerConnectionEndpoint connectionEndpoint,
@@ -225,8 +224,6 @@
defaultRedeliveryDelay = sp.getDefaultRedeliveryDelay();
deliveries = new ConcurrentHashMap();
-
- deliveryIdSequence = new SynchronizedLong(0);
}
// SessionDelegate implementation ---------------------------------------------------------------
@@ -344,77 +341,24 @@
if (sequence != 0)
{
- synchronized (waitLock)
- {
- long wait = CLOSE_WAIT_TIMEOUT;
-
- while (sequence != expectedSequence && wait > 0)
- {
- long start = System.currentTimeMillis();
- try
- {
- waitLock.wait();
- }
- catch (InterruptedException e)
- {
- }
- wait -= (System.currentTimeMillis() - start);
- }
-
- if (wait <= 0)
- {
- log.warn("Timed out waiting for last message");
- }
- }
+ reorderer.waitToArrive(sequence);
}
return -1;
}
- private volatile long expectedSequence = 0;
-
- private Map<Long, JBossMessage> heldBack = new HashMap<Long, JBossMessage>();
-
public void send(JBossMessage message, boolean checkForDuplicates) throws JMSException
{
throw new IllegalStateException("Should not be handled on the server");
}
-
- public void send(JBossMessage message, boolean checkForDuplicates, long thisSequence) throws JMSException
+
+ public void send(JBossMessage message, final boolean checkForDuplicates, long thisSequence) throws JMSException
{
try
{
if (thisSequence != -1)
{
- //Need to make sure it is in correct order since np messages are sent
- //one way so they can arrive out of sequence
-
- //This is a workaround to allow us to use one way messages for np messages for performance
- //reasons
-
- synchronized (waitLock)
- {
- if (thisSequence == expectedSequence)
- {
- do
- {
- connectionEndpoint.sendMessage(message, null, checkForDuplicates);
-
- expectedSequence++;
-
- message = (JBossMessage)heldBack.remove(expectedSequence);
-
- } while (message != null);
- }
- else
- {
- //Not the expected one - add it to the map
-
- heldBack.put(thisSequence, message);
- }
-
- waitLock.notify();
- }
+ reorderer.handle(message, thisSequence);
}
else
{
@@ -645,7 +589,7 @@
}
}
- this.deliveryIdSequence = new SynchronizedLong(maxDeliveryId + 1);
+ deliveryIdSequence = maxDeliveryId + 1;
}
catch (Throwable t)
{
@@ -1331,7 +1275,7 @@
DeliveryRecord rec = null;
- deliveryId = deliveryIdSequence.increment();
+ deliveryId = deliveryIdSequence++;
if (trace) { log.trace("Delivery id is now " + deliveryId); }
@@ -1459,39 +1403,17 @@
try
{
- // FIXME - due a design (flaw??) in the socket based transports, they use a pool of TCP
- // connections, so subsequent invocations can end up using different underlying
- // connections meaning that later invocations can overtake earlier invocations, if there
- // are more than one user concurrently invoking on the same transport. We need someway
- // of pinning the client object to the underlying invocation. For now we just serialize
- // all access so that only the first connection in the pool is ever used - but this is
- // far from ideal!!!
- // See http://jira.jboss.com/jira/browse/JBMESSAGING-789
-
- Object invoker = null;
-
- if (callbackClient != null)
- {
- invoker = callbackClient.getInvoker();
- }
- else
- {
- // TODO: dummy synchronization object, in case there's no clientInvoker. This will
- // happen during the first invocation anyway. It's a kludge, I know, but this whole
- // synchronization thing is a huge kludge. Needs to be reviewed.
- invoker = new Object();
- }
+ //Note - even though remoting cannot guarantee ordering of one way invocations unless client pool size =1
+ //in which case performance would be crippled - so this is not an option.
+ //We use a reorderer on the client side to re-order deliveries that may have got out of order
- synchronized (invoker)
- {
- // one way invocation, no acknowledgment sent back by the client
- if (trace) { log.trace(this + " submitting message " + ref.getMessage() + " to the remoting layer to be sent asynchronously"); }
-
- callbackHandler.handleCallbackOneway(callback);
-
- //We store the delivery id so we know to wait for any deliveries in transit on close
- consumer.setLastDeliveryID(deliveryID);
- }
+ // one way invocation, no acknowledgment sent back by the client
+ if (trace) { log.trace(this + " submitting message " + ref.getMessage() + " to the remoting layer to be sent asynchronously"); }
+
+ callbackHandler.handleCallbackOneway(callback);
+
+ //We store the delivery id so we know to wait for any deliveries in transit on close
+ consumer.setLastDeliveryID(deliveryID);
}
catch (Throwable t)
{
@@ -2412,4 +2334,12 @@
delList.add(deliveryId);
}
}
+
+ private class SendReorderer extends Reorderer
+ {
+ public void execute(Object object) throws Exception
+ {
+ connectionEndpoint.sendMessage((JBossMessage)object, null, false);
+ }
+ }
}
Added: branches/Branch_Stable/src/main/org/jboss/messaging/util/Reorderer.java
===================================================================
--- branches/Branch_Stable/src/main/org/jboss/messaging/util/Reorderer.java (rev 0)
+++ branches/Branch_Stable/src/main/org/jboss/messaging/util/Reorderer.java 2007-11-27 19:43:01 UTC (rev 3371)
@@ -0,0 +1,107 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2005, JBoss Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.messaging.util;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.jboss.logging.Logger;
+
+/**
+ *
+ * A Reorderer
+ *
+ * @author <a href="mailto:tim.fox at jboss.com">Tim Fox</a>
+ *
+ */
+public abstract class Reorderer
+{
+ private static final Logger log = Logger.getLogger(Reorderer.class);
+
+ private static final long WAIT_TIMEOUT = 5 * 1000;
+
+ private long expectedSequence = 0;
+
+ private Map<Long, Object> heldBack = new HashMap<Long, Object>();
+
+ public synchronized void reset()
+ {
+ heldBack.clear();
+
+ expectedSequence = 0;
+ }
+
+ public synchronized void handle(Object object, long thisSequence) throws Exception
+ {
+ //Need to make sure it is in correct order since np messages are sent
+ //one way so they can arrive out of sequence
+
+ //This is a workaround to allow us to use one way messages for np messages for performance
+ //reasons
+
+ if (thisSequence == expectedSequence)
+ {
+ do
+ {
+ execute(object);
+
+ expectedSequence++;
+
+ object = heldBack.remove(expectedSequence);
+
+ } while (object != null);
+ }
+ else
+ {
+ //Not the expected one - add it to the map
+
+ heldBack.put(thisSequence, object);
+ }
+
+ notify();
+ }
+
+ public synchronized void waitToArrive(long sequence)
+ {
+ long wait = WAIT_TIMEOUT;
+
+ while (sequence != expectedSequence && wait > 0)
+ {
+ long start = System.currentTimeMillis();
+ try
+ {
+ wait();
+ }
+ catch (InterruptedException e)
+ {
+ }
+ wait -= (System.currentTimeMillis() - start);
+ }
+
+ if (wait <= 0)
+ {
+ log.warn("Timed out waiting for last message");
+ }
+ }
+
+ public abstract void execute(Object object) throws Exception;
+}
Added: branches/Branch_Stable/tests/src/org/jboss/test/messaging/util/ReordererTest.java
===================================================================
--- branches/Branch_Stable/tests/src/org/jboss/test/messaging/util/ReordererTest.java (rev 0)
+++ branches/Branch_Stable/tests/src/org/jboss/test/messaging/util/ReordererTest.java 2007-11-27 19:43:01 UTC (rev 3371)
@@ -0,0 +1,188 @@
+/**
+ * JBoss, Home of Professional Open Source
+ *
+ * Distributable under LGPL license.
+ * See terms of license at gnu.org.
+ */
+package org.jboss.test.messaging.util;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.jboss.messaging.util.Reorderer;
+import org.jboss.test.messaging.MessagingTestCase;
+
+/**
+ *
+ * A ReordererTest
+ *
+ * @author <a href="mailto:tim.fox at jboss.com">Tim Fox</a>
+ *
+ */
+public class ReordererTest extends MessagingTestCase
+{
+ // Constants ------------------------------------------------------------------------------------
+
+ // Static ---------------------------------------------------------------------------------------
+
+ // Attributes -----------------------------------------------------------------------------------
+
+ // Constructors ---------------------------------------------------------------------------------
+
+ public ReordererTest(String name)
+ {
+ super(name);
+ }
+
+ // Public ---------------------------------------------------------------------------------------
+
+ public void testOrder() throws Exception
+ {
+ final List<Integer> list = new ArrayList<Integer>();
+
+ class MyReorderer extends Reorderer
+ {
+ @Override
+ public void execute(Object object) throws Exception
+ {
+ list.add((Integer)object);
+ }
+ }
+
+ Reorderer reorderer = new MyReorderer();
+
+ reorderer.handle(3, 3);
+ reorderer.handle(1, 1);
+ reorderer.handle(9, 9);
+ reorderer.handle(6, 6);
+ reorderer.handle(0, 0);
+ reorderer.handle(2, 2);
+ reorderer.handle(5, 5);
+ reorderer.handle(8, 8);
+ reorderer.handle(7, 7);
+ reorderer.handle(4, 4);
+
+ for (int i = 0; i < 10; i++)
+ {
+ assertEquals(Integer.valueOf(i), (Integer)list.get(i));
+ }
+
+ }
+
+ public void testHoldBack() throws Exception
+ {
+ final List<Integer> list = new ArrayList<Integer>();
+
+ class MyReorderer extends Reorderer
+ {
+ @Override
+ public void execute(Object object) throws Exception
+ {
+ list.add((Integer)object);
+ }
+ }
+
+ Reorderer reorderer = new MyReorderer();
+
+ reorderer.handle(3, 3);
+ assertTrue(list.isEmpty());
+ reorderer.handle(1, 1);
+ assertTrue(list.isEmpty());
+ reorderer.handle(9, 9);
+ assertTrue(list.isEmpty());
+ reorderer.handle(6, 6);
+ assertTrue(list.isEmpty());
+ reorderer.handle(0, 0);
+ assertEquals(Integer.valueOf(0), (Integer)list.get(0));
+ assertEquals(Integer.valueOf(1), (Integer)list.get(1));
+ assertEquals(2, list.size());
+ reorderer.handle(2, 2);
+ assertEquals(Integer.valueOf(0), (Integer)list.get(0));
+ assertEquals(Integer.valueOf(1), (Integer)list.get(1));
+ assertEquals(Integer.valueOf(2), (Integer)list.get(2));
+ assertEquals(Integer.valueOf(3), (Integer)list.get(3));
+ assertEquals(4, list.size());
+ reorderer.handle(5, 5);
+ assertEquals(Integer.valueOf(0), (Integer)list.get(0));
+ assertEquals(Integer.valueOf(1), (Integer)list.get(1));
+ assertEquals(Integer.valueOf(2), (Integer)list.get(2));
+ assertEquals(Integer.valueOf(3), (Integer)list.get(3));
+ assertEquals(4, list.size());
+ reorderer.handle(4, 4);
+ assertEquals(Integer.valueOf(0), (Integer)list.get(0));
+ assertEquals(Integer.valueOf(1), (Integer)list.get(1));
+ assertEquals(Integer.valueOf(2), (Integer)list.get(2));
+ assertEquals(Integer.valueOf(3), (Integer)list.get(3));
+ assertEquals(Integer.valueOf(4), (Integer)list.get(4));
+ assertEquals(Integer.valueOf(5), (Integer)list.get(5));
+ assertEquals(Integer.valueOf(6), (Integer)list.get(6));
+ assertEquals(7, list.size());
+ reorderer.handle(8, 8);
+ assertEquals(Integer.valueOf(0), (Integer)list.get(0));
+ assertEquals(Integer.valueOf(1), (Integer)list.get(1));
+ assertEquals(Integer.valueOf(2), (Integer)list.get(2));
+ assertEquals(Integer.valueOf(3), (Integer)list.get(3));
+ assertEquals(Integer.valueOf(4), (Integer)list.get(4));
+ assertEquals(Integer.valueOf(5), (Integer)list.get(5));
+ assertEquals(Integer.valueOf(6), (Integer)list.get(6));
+ assertEquals(7, list.size());
+ reorderer.handle(7, 7);
+ assertEquals(Integer.valueOf(0), (Integer)list.get(0));
+ assertEquals(Integer.valueOf(1), (Integer)list.get(1));
+ assertEquals(Integer.valueOf(2), (Integer)list.get(2));
+ assertEquals(Integer.valueOf(3), (Integer)list.get(3));
+ assertEquals(Integer.valueOf(4), (Integer)list.get(4));
+ assertEquals(Integer.valueOf(5), (Integer)list.get(5));
+ assertEquals(Integer.valueOf(6), (Integer)list.get(6));
+ assertEquals(Integer.valueOf(7), (Integer)list.get(7));
+ assertEquals(Integer.valueOf(8), (Integer)list.get(8));
+ assertEquals(Integer.valueOf(9), (Integer)list.get(9));
+ assertEquals(10, list.size());
+
+
+ for (int i = 0; i < 10; i++)
+ {
+ assertEquals(Integer.valueOf(i), (Integer)list.get(i));
+ }
+
+ }
+
+ public void testOrderMustStartWithZero() throws Exception
+ {
+ final List<Integer> list = new ArrayList<Integer>();
+
+ class MyReorderer extends Reorderer
+ {
+ @Override
+ public void execute(Object object) throws Exception
+ {
+ list.add((Integer)object);
+ }
+ }
+
+ Reorderer reorderer = new MyReorderer();
+
+ reorderer.handle(3, 3);
+ reorderer.handle(1, 1);
+ reorderer.handle(9, 9);
+ reorderer.handle(6, 6);
+ reorderer.handle(2, 2);
+ reorderer.handle(5, 5);
+ reorderer.handle(8, 8);
+ reorderer.handle(7, 7);
+ reorderer.handle(4, 4);
+
+ assertTrue(list.isEmpty());
+
+ }
+
+ // Package protected ----------------------------------------------------------------------------
+
+ // Protected ------------------------------------------------------------------------------------
+
+ // Private --------------------------------------------------------------------------------------
+
+ // Inner classes --------------------------------------------------------------------------------
+
+
+}
More information about the jboss-cvs-commits
mailing list