import io.netty.util.HashedWheelTimer;
import io.netty.util.Timeout;
import java.math.BigInteger;
-import java.util.Collection;
-import java.util.Collections;
+import java.util.ArrayList;
import java.util.HashMap;
-import java.util.HashSet;
-import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
private final DeviceFlowRegistry deviceFlowRegistry;
private final DeviceGroupRegistry deviceGroupRegistry;
private final DeviceMeterRegistry deviceMeterRegistry;
- private final Collection<DeviceContextClosedHandler> closeHandlers = new HashSet<>();
+ private final List<DeviceContextClosedHandler> closeHandlers = new ArrayList<>(4);
private final PacketInRateLimiter packetInLimiter;
private final MessageSpy messageSpy;
private final ItemLifeCycleKeeper flowLifeCycleKeeper;
LOG.trace("onClusterRoleChange {} for node:", role, deviceState.getNodeId());
Preconditions.checkArgument(role != null);
if (role.equals(oldRole)) {
- LOG.debug("Demanded role change for device {} is not change OldRole: {}, NewRole {}", deviceState.getNodeId(), oldRole, role);
+ LOG.debug("Demanded role change for device {} is not changed. OldRole: {}, NewRole {}", deviceState.getNodeId(), oldRole, role);
return Futures.immediateFuture(null);
}
if (OfpRole.BECOMEMASTER.equals(role)) {
LOG.info("Closing transaction chain manager without cleaning inventory operational");
transactionChainManager.close();
- final LinkedList<DeviceContextClosedHandler> reversedCloseHandlers = new LinkedList<>(closeHandlers);
- Collections.reverse(reversedCloseHandlers);
- for (final DeviceContextClosedHandler deviceContextClosedHandler : reversedCloseHandlers) {
+ // call closeHandlers in the reverse order
+ for (int i=(closeHandlers.size() - 1); i >=0; i--) {
+ DeviceContextClosedHandler deviceContextClosedHandler = closeHandlers.get(i);
deviceContextClosedHandler.onDeviceContextClosed(this);
}
closeHandlers.clear();
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
-
-import java.math.BigInteger;
-import java.net.InetSocketAddress;
-import java.util.concurrent.atomic.AtomicLong;
-
import com.google.common.base.Optional;
import com.google.common.collect.Lists;
import com.google.common.util.concurrent.CheckedFuture;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.SettableFuture;
+import com.google.common.util.concurrent.Uninterruptibles;
import io.netty.util.HashedWheelTimer;
import io.netty.util.Timeout;
+import java.math.BigInteger;
+import java.net.InetSocketAddress;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicLong;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Ignore;
Assert.assertEquals(0, deviceContext.getDeviceMeterRegistry().getAllMeterIds().size());
}
+
+ @Test
+ public void testDeviceDisconnectedHandlerExecutionOrder() throws Exception {
+ DeviceState deviceState = new DeviceStateImpl(mock(FeaturesReply.class), mock(NodeId.class));
+ DeviceContext deviceContext1 = new DeviceContextImpl(connectionContext, deviceState, dataBroker, timer,
+ messageIntelligenceAgency, outboundQueueProvider, translatorLibrary, false);
+
+ deviceState.setValid(true);
+ when(txChainManager.shuttingDown()).thenReturn(Futures.immediateFuture((Void) null));
+
+ List<Integer> executionOrderList = new ArrayList<>(4);
+
+ DeviceContextClosedHandler deviceContextClosedHandler1 = new OrderedDeviceContextClosedHandler(1, executionOrderList);
+ DeviceContextClosedHandler deviceContextClosedHandler2 = new OrderedDeviceContextClosedHandler(2, executionOrderList);
+ DeviceContextClosedHandler deviceContextClosedHandler3 = new OrderedDeviceContextClosedHandler(3, executionOrderList);
+ DeviceContextClosedHandler deviceContextClosedHandler4 = new OrderedDeviceContextClosedHandler(4, executionOrderList);
+
+ deviceContext1.addDeviceContextClosedHandler(deviceContextClosedHandler1);
+ deviceContext1.addDeviceContextClosedHandler(deviceContextClosedHandler2);
+ deviceContext1.addDeviceContextClosedHandler(deviceContextClosedHandler3);
+ deviceContext1.addDeviceContextClosedHandler(deviceContextClosedHandler4);
+
+ deviceContext1.onDeviceDisconnected(connectionContext);
+
+ Uninterruptibles.sleepUninterruptibly(2, TimeUnit.SECONDS);
+
+ assertEquals("Not all DeviceContextClosedHandler got executed", 4, executionOrderList.size());
+ assertEquals("DeviceContextClosedHandler execution is not correct", 4, executionOrderList.get(0).intValue());
+ assertEquals("DeviceContextClosedHandler execution is not correct", 3, executionOrderList.get(1).intValue());
+ assertEquals("DeviceContextClosedHandler execution is not correct", 2, executionOrderList.get(2).intValue());
+ assertEquals("DeviceContextClosedHandler execution is not correct", 1, executionOrderList.get(3).intValue());
+ }
+
+ private class OrderedDeviceContextClosedHandler implements DeviceContextClosedHandler {
+
+ private final int order;
+ private final List<Integer> executionOrderList;
+
+ public OrderedDeviceContextClosedHandler(int order, List<Integer> executionOrderList ) {
+
+ this.order = order;
+ this.executionOrderList = executionOrderList;
+ }
+
+ @Override
+ public void onDeviceContextClosed(DeviceContext deviceContext) {
+ executionOrderList.add(order);
+ }
+ }
}