Merge "BUG-4148: Improving the logging in flow/group/meter to provide more contextual...
authorAbhijit Kumbhare <abhijit.kumbhare@ericsson.com>
Sat, 14 May 2016 04:23:00 +0000 (04:23 +0000)
committerGerrit Code Review <gerrit@opendaylight.org>
Sat, 14 May 2016 04:23:00 +0000 (04:23 +0000)
48 files changed:
applications/statistics-manager/src/main/java/org/opendaylight/openflowplugin/applications/statistics/manager/impl/helper/MatchComparatorHelper.java
openflowplugin-api/src/main/java/org/opendaylight/openflowplugin/api/openflow/device/DeviceContext.java
openflowplugin-api/src/main/java/org/opendaylight/openflowplugin/api/openflow/device/DeviceManager.java
openflowplugin-api/src/main/java/org/opendaylight/openflowplugin/api/openflow/device/XidSequencer.java [new file with mode: 0644]
openflowplugin-api/src/main/java/org/opendaylight/openflowplugin/api/openflow/device/handlers/DeviceConnectedHandler.java
openflowplugin-api/src/main/java/org/opendaylight/openflowplugin/api/openflow/device/handlers/DeviceInitializationPhaseHandler.java
openflowplugin-api/src/main/java/org/opendaylight/openflowplugin/api/openflow/lifecycle/DeviceContextChangeListener.java [new file with mode: 0644]
openflowplugin-api/src/main/java/org/opendaylight/openflowplugin/api/openflow/lifecycle/LifecycleConductor.java [new file with mode: 0644]
openflowplugin-api/src/main/java/org/opendaylight/openflowplugin/api/openflow/lifecycle/RoleChangeListener.java [new file with mode: 0644]
openflowplugin-api/src/main/java/org/opendaylight/openflowplugin/api/openflow/lifecycle/ServiceChangeListener.java [new file with mode: 0644]
openflowplugin-api/src/main/java/org/opendaylight/openflowplugin/api/openflow/role/RoleChangeListener.java [deleted file]
openflowplugin-api/src/main/java/org/opendaylight/openflowplugin/api/openflow/role/RoleContext.java
openflowplugin-api/src/main/java/org/opendaylight/openflowplugin/api/openflow/role/RoleManager.java
openflowplugin-api/src/main/java/org/opendaylight/openflowplugin/api/openflow/rpc/RpcContext.java
openflowplugin-api/src/main/java/org/opendaylight/openflowplugin/api/openflow/rpc/RpcManager.java
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/LifecycleConductorImpl.java [new file with mode: 0644]
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/OpenFlowPluginProviderImpl.java
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/connection/ConnectionContextImpl.java
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/connection/listener/HandshakeListenerImpl.java
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/device/DeviceContextImpl.java
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/device/DeviceManagerImpl.java
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/device/TransactionChainManager.java
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/role/RoleContextImpl.java
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/role/RoleManagerImpl.java
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/rpc/RpcContextImpl.java
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/rpc/RpcManagerImpl.java
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/rpc/listener/ItemLifecycleListenerImpl.java
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/services/SalTableServiceImpl.java
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/statistics/StatisticsContextImpl.java
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/statistics/StatisticsGatheringUtils.java
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/statistics/StatisticsManagerImpl.java
openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/util/DeviceInitializationUtils.java
openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/device/DeviceContextImplTest.java
openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/device/DeviceManagerImplTest.java
openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/role/RoleContextImplTest.java
openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/role/RoleManagerImplTest.java [new file with mode: 0644]
openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/rpc/RpcContextImplTest.java
openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/rpc/RpcManagerImplTest.java
openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/services/MultipartRequestOnTheFlyCallbackTest.java
openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/services/ServiceMocking.java
openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/statistics/StatisticsContextImpMockInitiation.java
openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/statistics/StatisticsContextImplParamTest.java
openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/statistics/StatisticsContextImplTest.java
openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/statistics/StatisticsGatheringUtilsTest.java
openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/statistics/StatisticsManagerImplTest.java
openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/util/DeviceInitializationUtilsTest.java
openflowplugin/src/main/java/org/opendaylight/openflowplugin/openflow/md/util/OpenflowPortsUtil.java
parent/pom.xml

index 6762fea79f60105d182261a825202654a9ec8aac..aa4f756007781a97cab86cd9ff2476056ee37e9a 100644 (file)
@@ -20,8 +20,12 @@ import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev100924.MacAddress;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.DottedQuad;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.MacAddressFilter;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.arp.match.fields.ArpSourceHardwareAddress;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.arp.match.fields.ArpTargetHardwareAddress;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.arp.match.fields.ArpTargetHardwareAddressBuilder;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.EthernetMatch;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.Layer3Match;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._3.match.ArpMatch;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._3.match.Ipv4Match;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._3.match.Ipv4MatchArbitraryBitMask;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.model.match.types.rev131026.match.layer._3.match.Ipv6Match;
@@ -206,6 +210,8 @@ public class MatchComparatorHelper {
                 }
                 verdict = MatchComparatorHelper.compareIpv4PrefixNullSafe(ipv4PrefixSource, statsIpv4Match.getIpv4Source());
             }
+        } else if (statsLayer3Match instanceof ArpMatch && storedLayer3Match instanceof ArpMatch) {
+            verdict = arpMatchEquals((ArpMatch)statsLayer3Match, (ArpMatch)storedLayer3Match);
         } else {
             final Boolean nullCheckOut = checkNullValues(storedLayer3Match, statsLayer3Match);
             if (nullCheckOut != null) {
@@ -217,6 +223,47 @@ public class MatchComparatorHelper {
         return verdict;
     }
 
+    static boolean arpMatchEquals(final ArpMatch statsArpMatch, final ArpMatch storedArpMatch) {
+
+        Integer statsOp = statsArpMatch.getArpOp();
+        Integer storedOp = storedArpMatch.getArpOp();
+
+        Boolean nullCheck = checkNullValues(statsOp, storedOp);
+        if (nullCheck != null) {
+            if (nullCheck == false) {
+                return false;
+            }
+        } else if (!statsOp.equals(storedOp)) {
+            return false;
+        }
+
+        Ipv4Prefix statsIp = statsArpMatch.getArpSourceTransportAddress();
+        Ipv4Prefix storedIp = storedArpMatch.getArpSourceTransportAddress();
+        if (!compareIpv4PrefixNullSafe(statsIp, storedIp)) {
+            return false;
+        }
+
+        statsIp = statsArpMatch.getArpTargetTransportAddress();
+        storedIp = storedArpMatch.getArpTargetTransportAddress();
+        if (!compareIpv4PrefixNullSafe(statsIp, storedIp)) {
+            return false;
+        }
+
+        MacAddressFilter statsMac = statsArpMatch.getArpSourceHardwareAddress();
+        MacAddressFilter storedMac = storedArpMatch.getArpSourceHardwareAddress();
+        if (!ethernetMatchFieldsEquals(statsMac, storedMac)) {
+            return false;
+        }
+
+        statsMac = statsArpMatch.getArpTargetHardwareAddress();
+        storedMac = storedArpMatch.getArpTargetHardwareAddress();
+        if (!ethernetMatchFieldsEquals(statsMac, storedMac)) {
+            return false;
+        }
+
+        return true;
+    }
+
 
     /**
      * TODO: why don't we use the default Ipv4Prefix.equals()?
index f3497393cdd34939d06a7977c2dec70bc470a3b6..62188f8fdf66c988d62f4d5b3530e5fc417e4c01 100644 (file)
@@ -21,7 +21,6 @@ import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
 import org.opendaylight.openflowplugin.api.openflow.OpenFlowPluginTimer;
 import org.opendaylight.openflowplugin.api.openflow.connection.ConnectionContext;
 import org.opendaylight.openflowplugin.api.openflow.device.handlers.DeviceReplyProcessor;
-import org.opendaylight.openflowplugin.api.openflow.device.handlers.DeviceTerminationPhaseHandler;
 import org.opendaylight.openflowplugin.api.openflow.device.handlers.MultiMsgCollector;
 import org.opendaylight.openflowplugin.api.openflow.registry.ItemLifeCycleRegistry;
 import org.opendaylight.openflowplugin.api.openflow.registry.flow.DeviceFlowRegistry;
@@ -53,9 +52,11 @@ import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
  * Created by Martin Bobak &lt;mbobak@cisco.com&gt; on 25.2.2015.
  */
 public interface DeviceContext extends AutoCloseable,
-        OpenFlowPluginTimer,
         DeviceReplyProcessor,
-        PortNumberCache {
+        PortNumberCache,
+        XidSequencer {
+
+    void setStatisticsRpcEnabled(boolean isStatisticsRpcEnabled);
 
     /**
      * distinguished device context states
@@ -140,12 +141,12 @@ public interface DeviceContext extends AutoCloseable,
     /**
      * Method creates put operation using provided data in underlying transaction chain.
      */
-    <T extends DataObject> void writeToTransaction(final LogicalDatastoreType store, final InstanceIdentifier<T> path, final T data);
+    <T extends DataObject> void writeToTransaction(final LogicalDatastoreType store, final InstanceIdentifier<T> path, final T data) throws Exception;
 
     /**
      * Method creates delete operation for provided path in underlying transaction chain.
      */
-    <T extends DataObject> void addDeleteToTxChain(final LogicalDatastoreType store, final InstanceIdentifier<T> path);
+    <T extends DataObject> void addDeleteToTxChain(final LogicalDatastoreType store, final InstanceIdentifier<T> path) throws Exception;
 
     /**
      * Method submits Transaction to DataStore.
@@ -220,31 +221,12 @@ public interface DeviceContext extends AutoCloseable,
      */
     Timeout getBarrierTaskTimeout();
 
-    /**
-     * Sets notification service
-     *
-     * @param notificationService
-     */
-    void setNotificationService(NotificationService notificationService);
-
     void setNotificationPublishService(NotificationPublishService notificationPublishService);
 
     MessageSpy getMessageSpy();
 
-    /**
-     * Method sets reference to handler used for cleanup after device context about to be closed.
-     */
-    void addDeviceContextClosedHandler(DeviceTerminationPhaseHandler deviceContextClosedHandler);
-
     MultiMsgCollector getMultiMsgCollector(final RequestContext<List<MultipartReply>> requestContext);
 
-    /**
-     * Method is reserved unique XID for Device Message.
-     * Attention: OFJava expect the message, otherwise OutboundQueue could stop working.
-     * @return Reserved XID
-     */
-    Long reservedXidForDeviceMessage();
-
     /**
      * indicates that device context is fully published (e.g.: packetIn messages should be passed)
      */
index 4e89cd9adf9b9179e89b0f271c3692e1ab964c6c..3af5e496428bf83d98bb3f948ae68d1eb52dad49 100644 (file)
@@ -16,6 +16,7 @@ import org.opendaylight.openflowplugin.api.openflow.device.handlers.DeviceInitia
 import org.opendaylight.openflowplugin.api.openflow.device.handlers.DeviceLifecycleSupervisor;
 import org.opendaylight.openflowplugin.api.openflow.device.handlers.DeviceTerminationPhaseHandler;
 import org.opendaylight.openflowplugin.api.openflow.translator.TranslatorLibrarian;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
 
 /**
  * This interface is responsible for instantiating DeviceContext and
@@ -26,13 +27,6 @@ import org.opendaylight.openflowplugin.api.openflow.translator.TranslatorLibrari
 public interface DeviceManager extends DeviceConnectedHandler, DeviceDisconnectedHandler, DeviceLifecycleSupervisor,
         DeviceInitializationPhaseHandler, DeviceTerminationPhaseHandler, TranslatorLibrarian, AutoCloseable {
 
-    /**
-     * Sets notification receiving service
-     *
-     * @param notificationService
-     */
-    void setNotificationService(NotificationService notificationService);
-
     /**
      * Sets notification publish service
      *
@@ -44,5 +38,16 @@ public interface DeviceManager extends DeviceConnectedHandler, DeviceDisconnecte
      * invoked after all services injected
      */
     void initialize();
+
+    /**
+     * Returning device context from map maintained in device manager
+     * This prevent to send whole device context to another context
+     * If device context not exists for nodeId it will return null
+     * @param nodeId
+     * @return device context or null
+     */
+    DeviceContext getDeviceContextFromNodeId(NodeId nodeId);
+
+    void setStatisticsRpcEnabled(boolean isStatisticsRpcEnabled);
 }
 
diff --git a/openflowplugin-api/src/main/java/org/opendaylight/openflowplugin/api/openflow/device/XidSequencer.java b/openflowplugin-api/src/main/java/org/opendaylight/openflowplugin/api/openflow/device/XidSequencer.java
new file mode 100644 (file)
index 0000000..5bdfa05
--- /dev/null
@@ -0,0 +1,22 @@
+/*
+ * Copyright (c) 2015 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.openflowplugin.api.openflow.device;
+
+/**
+ * Reserves unique XID for Device Messages.
+ */
+public interface XidSequencer {
+
+    /**
+     * Method reserve unique XID for Device Message.
+     * Attention: OFJava expect the message, otherwise OutboundQueue could stop working.
+     * @return Reserved XID
+     */
+    Long reserveXidForDeviceMessage();
+}
index 005a2de0583ec4ab543e34323a417f6bf721b61d..8900357eb5f0e03503ccfa5fb6c009e80f38366b 100644 (file)
@@ -19,6 +19,6 @@ public interface DeviceConnectedHandler {
      * Method is used to propagate information about established connection with device.
      * It propagates connected device's connection context.
      */
-    void deviceConnected(ConnectionContext connectionContext) throws Exception;
+    boolean deviceConnected(ConnectionContext connectionContext) throws Exception;
 
 }
index 53b48b4f2c1154845c7de28734da1d48390f77ab..3e7bf34298fe063ec52d6219074001c24486470c 100644 (file)
@@ -10,6 +10,7 @@ package org.opendaylight.openflowplugin.api.openflow.device.handlers;
 
 import javax.annotation.CheckForNull;
 import org.opendaylight.openflowplugin.api.openflow.device.DeviceContext;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
 
 /**
  * openflowplugin-api
@@ -25,8 +26,8 @@ public interface DeviceInitializationPhaseHandler {
     /**
      * Method represents an initialization cycle for {@link DeviceContext} preparation for use.
      *
-     * @param deviceContext
+     * @param nodeId
      * @throws Exception - needs to be catch in ConnectionHandler implementation
      */
-    void onDeviceContextLevelUp(@CheckForNull DeviceContext deviceContext) throws Exception;
+    void onDeviceContextLevelUp(@CheckForNull NodeId nodeId) throws Exception;
 }
diff --git a/openflowplugin-api/src/main/java/org/opendaylight/openflowplugin/api/openflow/lifecycle/DeviceContextChangeListener.java b/openflowplugin-api/src/main/java/org/opendaylight/openflowplugin/api/openflow/lifecycle/DeviceContextChangeListener.java
new file mode 100644 (file)
index 0000000..a3ca90d
--- /dev/null
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2016 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.openflowplugin.api.openflow.lifecycle;
+
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.role.service.rev150727.OfpRole;
+
+/**
+ * This API is for all listeners who wish to know about device context in cluster
+ */
+public interface DeviceContextChangeListener {
+
+    /**
+     * Notification about start phase in device context, right after successful handshake
+     * @param nodeId
+     * @param success or failure
+     */
+    void deviceStartInitializationDone(final NodeId nodeId, final boolean success);
+
+    /**
+     * Notification about start phase in device context, after all other contexts initialized properly
+     * @param nodeId
+     * @param success
+     */
+    void deviceInitializationDone(final NodeId nodeId, final boolean success);
+
+}
diff --git a/openflowplugin-api/src/main/java/org/opendaylight/openflowplugin/api/openflow/lifecycle/LifecycleConductor.java b/openflowplugin-api/src/main/java/org/opendaylight/openflowplugin/api/openflow/lifecycle/LifecycleConductor.java
new file mode 100644 (file)
index 0000000..63042e0
--- /dev/null
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 2016 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.openflowplugin.api.openflow.lifecycle;
+
+import io.netty.util.Timeout;
+import io.netty.util.TimerTask;
+import org.opendaylight.openflowplugin.api.openflow.device.DeviceContext;
+import org.opendaylight.openflowplugin.api.openflow.device.DeviceManager;
+import org.opendaylight.openflowplugin.api.openflow.statistics.ofpspecific.MessageIntelligenceAgency;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
+
+import javax.annotation.Nonnull;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * This class is a binder between all managers
+ * Should be defined in OpenFlowPluginProviderImpl
+ */
+public interface LifecycleConductor {
+
+    /**
+     * Returns device context from device manager device contexts maps
+     * @param nodeId node identification
+     * @return null if context doesn't exists
+     */
+    DeviceContext getDeviceContext(final NodeId nodeId);
+
+    /**
+     * Registers ont time listener for notify when services rpc, statistics are done stop or start
+     * @param manager service change listener
+     * @param nodeId node identification
+     */
+    void addOneTimeListenerWhenServicesChangesDone(final ServiceChangeListener manager, final NodeId nodeId);
+
+    /**
+     * Returns device of version
+     * @param nodeId node identification
+     * @return null if device context doesn't exists
+     */
+    Short gainVersionSafely(final NodeId nodeId);
+
+    /**
+     * Set new timeout for {@link io.netty.util.HashedWheelTimer}
+     * @param task timer task
+     * @param delay delay
+     * @param unit time unit
+     * @return new timeout
+     */
+    Timeout newTimeout(@Nonnull TimerTask task, long delay, @Nonnull TimeUnit unit);
+
+    /**
+     * Returns message intelligence agency
+     * @return MessageIntelligenceAgency set by constructor
+     */
+    MessageIntelligenceAgency getMessageIntelligenceAgency();
+
+    /**
+     * Interrupt connection for the node
+     * @param nodeId node identification
+     */
+    void closeConnection(final NodeId nodeId);
+
+    /**
+     * Setter for device manager once set it cant be unset or overwritten
+     * @param deviceManager should be set in OpenFlowPluginProviderImpl
+     */
+    void setSafelyDeviceManager(final DeviceManager deviceManager);
+
+    /**
+     * Xid from outboundqueue
+     * @param nodeId
+     * @return
+     */
+    Long reserveXidForDeviceMessage(final NodeId nodeId);
+}
diff --git a/openflowplugin-api/src/main/java/org/opendaylight/openflowplugin/api/openflow/lifecycle/RoleChangeListener.java b/openflowplugin-api/src/main/java/org/opendaylight/openflowplugin/api/openflow/lifecycle/RoleChangeListener.java
new file mode 100644 (file)
index 0000000..f830966
--- /dev/null
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2016 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.openflowplugin.api.openflow.lifecycle;
+
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.role.service.rev150727.OfpRole;
+
+/**
+ * This API is for all listeners who wish to know about role change in cluster
+ */
+public interface RoleChangeListener {
+
+    /**
+     * Notification when initialization for role context is done
+     * @param nodeId
+     * @param success or failure
+     */
+    void roleInitializationDone(final NodeId nodeId, final boolean success);
+
+    /**
+     * Notification when the role change on device is done
+     * @param nodeId
+     * @param success
+     * @param newRole
+     * @param initializationPhase
+     */
+    void roleChangeOnDevice(final NodeId nodeId, final boolean success, final OfpRole newRole, final boolean initializationPhase);
+
+}
diff --git a/openflowplugin-api/src/main/java/org/opendaylight/openflowplugin/api/openflow/lifecycle/ServiceChangeListener.java b/openflowplugin-api/src/main/java/org/opendaylight/openflowplugin/api/openflow/lifecycle/ServiceChangeListener.java
new file mode 100644 (file)
index 0000000..5afe5bb
--- /dev/null
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2016 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.openflowplugin.api.openflow.lifecycle;
+
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
+
+/**
+ * This API is defined for listening when services (Statistics and RPCs) are fully stopped
+ * or fully started. Role manager use it for unregister tx entity on shutdown when all is stopped.
+ */
+public interface ServiceChangeListener {
+
+    /**
+     * Notification when services (rpc, statistics) are started or stopped working
+     * @param nodeId
+     * @param success
+     */
+    void servicesChangeDone(NodeId nodeId, boolean success);
+
+}
diff --git a/openflowplugin-api/src/main/java/org/opendaylight/openflowplugin/api/openflow/role/RoleChangeListener.java b/openflowplugin-api/src/main/java/org/opendaylight/openflowplugin/api/openflow/role/RoleChangeListener.java
deleted file mode 100644 (file)
index 046c28e..0000000
+++ /dev/null
@@ -1,61 +0,0 @@
-/**
- * Copyright (c) 2015 Cisco Systems, Inc. and others.  All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-package org.opendaylight.openflowplugin.api.openflow.role;
-
-import org.opendaylight.controller.md.sal.common.api.clustering.Entity;
-import org.opendaylight.openflowplugin.api.openflow.device.DeviceState;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.role.service.rev150727.OfpRole;
-
-/**
- * Double candidate aproach brings protected role change for all node cluster instances.
- *
- * Created by kramesha on 9/19/15.
- */
-public interface RoleChangeListener extends AutoCloseable {
-
-    /**
-     * Method has to be called from MainCandidate Leaderhip notification {@link OfpRole#BECOMEMASTER}
-     * It locks any MainCandidate changes and it registrates TxCandidate to Cluster.
-     */
-    void onDeviceTryToTakeClusterLeadership();
-
-    /**
-     * Method has to be called from TxCandidate Leadership notification {@link OfpRole#BECOMEMASTER}
-     * and propagate {@link OfpRole#BECOMEMASTER} to device. When device accepts new role, it has to
-     * notifies whole DeviceContext suite to take Leadership responsibility
-     */
-    void onDeviceTakeClusterLeadership();
-
-    /**
-     * Method has to be called from MainCandidate Leadership notification {@link OfpRole#BECOMESLAVE}
-     * It locks any MainCandidate and TxCandidate changes and it starts propagate LostClusterLeadership
-     * to Device and whole DeviceContext suite.
-     */
-    void onDeviceLostClusterLeadership();
-
-    /**
-     * We need to know when the candidate is registrated or in close process
-     * @return true/false
-     */
-    boolean isMainCandidateRegistered();
-
-    /**
-     * We need to know when the candidate is registrated or in close process
-     * @return true/false
-     */
-    boolean isTxCandidateRegistered();
-
-    Entity getEntity();
-
-    Entity getTxEntity();
-
-    DeviceState getDeviceState();
-
-    @Override
-    void close();
-}
index 80a5838d7ea56d4aa494535e1c696f2d6429bdaf..5b9bbfdb331ead46ea1caa1e2bbb6ea18906ba07 100644 (file)
@@ -7,14 +7,17 @@
  */
 package org.opendaylight.openflowplugin.api.openflow.role;
 
-import org.opendaylight.openflowplugin.api.openflow.device.DeviceContext;
+import org.opendaylight.controller.md.sal.common.api.clustering.Entity;
 import org.opendaylight.openflowplugin.api.openflow.device.RequestContextStack;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.role.service.rev150727.OfpRole;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.role.service.rev150727.SalRoleService;
+
+import javax.annotation.Nonnull;
 
 /**
- * Created by kramesha on 9/12/15.
+ * Rewrote whole role context to prevent errors to change role on cluster
  */
-public interface RoleContext extends RoleChangeListener, RequestContextStack {
+public interface RoleContext extends  RequestContextStack, AutoCloseable {
 
     /**
      * Initialization method is responsible for a registration of
@@ -23,24 +26,82 @@ public interface RoleContext extends RoleChangeListener, RequestContextStack {
      * {@link org.opendaylight.controller.md.sal.common.api.clustering.EntityOwnershipService}
      * returns Role which has to be applied for responsible Device Context suite. Any Exception
      * state has to close Device connection channel.
+     * @return true if initialization done ok
      */
-    void initializationRoleContext();
+    boolean initialization();
 
     /**
-     * Termination method is responsible for an unregistrion of
+     * Termination method is responsible for an unregistration of
      * {@link org.opendaylight.controller.md.sal.common.api.clustering.Entity} and listener
      * for notification from service
      * {@link org.opendaylight.controller.md.sal.common.api.clustering.EntityOwnershipService}
      * returns notification "Someone else take Leadership" or "I'm last"
      * and we need to clean Oper. DS.
      */
-    void terminationRoleContext();
+    void unregisterAllCandidates();
 
-    @Override
-    void close();
+    /**
+     * Setter for sal role service
+     * @param salRoleService
+     */
+    void setSalRoleService(@Nonnull final SalRoleService salRoleService);
+
+    /**
+     * Getter for sal role service
+     * @return
+     */
+    SalRoleService getSalRoleService();
+
+    /**
+     * Getter for main entity
+     * @return
+     */
+    Entity getEntity();
+
+    /**
+     * Getter for tx entity
+     * @return
+     */
+    Entity getTxEntity();
+
+    /**
+     * Actual nodeId
+     * @return
+     */
+    NodeId getNodeId();
+
+    /**
+     * Returns true if main entity is registered
+     * @return
+     */
+    boolean isMainCandidateRegistered();
+
+    /**
+     * Returns true if tx entity is registered
+     * @return
+     */
+    boolean isTxCandidateRegistered();
+
+    /**
+     * Register candidate depending on parameter
+     * @param entity
+     * @return true is registration was successful
+     */
+    boolean registerCandidate(final Entity entity);
 
-    DeviceContext getDeviceContext();
+    /**
+     * Unregister candidate depending on parameter
+     * @param entity
+     * @return true is registration was successful
+     */
+    boolean unregisterCandidate(final Entity entity);
 
-    OfpRole getClusterRole();
+    /**
+     * Returns true if we hold both registrations
+     * @return
+     */
+    boolean isMaster();
 
+    @Override
+    void close();
 }
index 66d92d8806f46d6b9c7d49df854f770bf743308c..5a1bb0dbacc884d02ec9487f88a966cadb05f4aa 100644 (file)
@@ -10,12 +10,23 @@ package org.opendaylight.openflowplugin.api.openflow.role;
 import org.opendaylight.openflowplugin.api.openflow.device.handlers.DeviceTerminationPhaseHandler;
 import org.opendaylight.openflowplugin.api.openflow.device.handlers.DeviceInitializationPhaseHandler;
 import org.opendaylight.openflowplugin.api.openflow.device.handlers.DeviceLifecycleSupervisor;
+import org.opendaylight.openflowplugin.api.openflow.lifecycle.RoleChangeListener;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.role.service.rev150727.OfpRole;
 
 /**
  * Created by kramesha on 8/31/15.
  */
 public interface RoleManager extends DeviceLifecycleSupervisor, DeviceInitializationPhaseHandler, AutoCloseable,
         DeviceTerminationPhaseHandler {
-    public static final String ENTITY_TYPE = "openflow";
-    public static final String TX_ENTITY_TYPE = "ofTransaction";
+    String ENTITY_TYPE = "openflow";
+    String TX_ENTITY_TYPE = "ofTransaction";
+
+    /**
+     * Adding listener to by notified for role changes
+     * API for listener {@link RoleChangeListener}
+     * @param roleChangeListener
+     */
+    void addRoleChangeListener(RoleChangeListener roleChangeListener);
+
 }
index 7925e9da81bdb3eb1ea429158ebdc84c542d5ecb..4be56a094e788718ca86d5801819a6a9210ef5b2 100644 (file)
@@ -23,8 +23,6 @@ public interface RpcContext extends RequestContextStack, AutoCloseable {
     <S extends RpcService> S lookupRpcService(Class<S> serviceClass);
     <S extends RpcService> void unregisterRpcServiceImplementation(Class<S> serviceClass);
 
-    void registerStatCompatibilityServices();
-
     @Override
     void close();
 }
index fc63f9d09d591111899737de1ac89881162b28bd..f5c8e2894e91eb9d5910b64d9da9f00d1b53b479 100644 (file)
@@ -12,17 +12,15 @@ import org.opendaylight.openflowplugin.api.openflow.device.handlers.DeviceTermin
 import org.opendaylight.controller.md.sal.binding.api.NotificationPublishService;
 import org.opendaylight.openflowplugin.api.openflow.device.handlers.DeviceInitializationPhaseHandler;
 import org.opendaylight.openflowplugin.api.openflow.device.handlers.DeviceLifecycleSupervisor;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
 
 /**
  * The RPC Manager will maintain an RPC Context for each online switch. RPC context for device is created when
- * {@link org.opendaylight.openflowplugin.api.openflow.device.handlers.DeviceInitializationPhaseHandler#onDeviceContextLevelUp(org.opendaylight.openflowplugin.api.openflow.device.DeviceContext)}
+ * {@link org.opendaylight.openflowplugin.api.openflow.device.handlers.DeviceInitializationPhaseHandler#onDeviceContextLevelUp(NodeId)}
  * is called.
  * <p>
  * Created by Martin Bobak &lt;mbobak@cisco.com&gt; on 25.2.2015.
  */
 public interface RpcManager extends DeviceLifecycleSupervisor, DeviceInitializationPhaseHandler, AutoCloseable, DeviceTerminationPhaseHandler {
 
-    void setStatisticsRpcEnabled(boolean isStatisticsRpcEnabled);
-
-    void setNotificationPublishService(NotificationPublishService notificationPublishService);
 }
diff --git a/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/LifecycleConductorImpl.java b/openflowplugin-impl/src/main/java/org/opendaylight/openflowplugin/impl/LifecycleConductorImpl.java
new file mode 100644 (file)
index 0000000..f0ff123
--- /dev/null
@@ -0,0 +1,189 @@
+/*
+ * Copyright (c) 2016 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.openflowplugin.impl;
+
+import com.google.common.base.Preconditions;
+import com.google.common.util.concurrent.FutureCallback;
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.ListenableFuture;
+import io.netty.util.HashedWheelTimer;
+import io.netty.util.Timeout;
+import io.netty.util.TimerTask;
+import org.opendaylight.openflowplugin.api.openflow.connection.ConnectionContext;
+import org.opendaylight.openflowplugin.api.openflow.device.DeviceContext;
+import org.opendaylight.openflowplugin.api.openflow.device.DeviceManager;
+import org.opendaylight.openflowplugin.api.openflow.device.DeviceState;
+import org.opendaylight.openflowplugin.api.openflow.lifecycle.DeviceContextChangeListener;
+import org.opendaylight.openflowplugin.api.openflow.lifecycle.LifecycleConductor;
+import org.opendaylight.openflowplugin.api.openflow.lifecycle.RoleChangeListener;
+import org.opendaylight.openflowplugin.api.openflow.lifecycle.ServiceChangeListener;
+import org.opendaylight.openflowplugin.api.openflow.statistics.ofpspecific.MessageIntelligenceAgency;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.role.service.rev150727.OfpRole;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.TimeUnit;
+
+/**
+ */
+public final class LifecycleConductorImpl implements LifecycleConductor, RoleChangeListener, DeviceContextChangeListener {
+
+    private static final Logger LOG = LoggerFactory.getLogger(LifecycleConductorImpl.class);
+    private static final int TICKS_PER_WHEEL = 500;
+    private static final long TICK_DURATION = 10; // 0.5 sec.
+
+    private final HashedWheelTimer hashedWheelTimer = new HashedWheelTimer(TICK_DURATION, TimeUnit.MILLISECONDS, TICKS_PER_WHEEL);
+    private DeviceManager deviceManager;
+    private final MessageIntelligenceAgency messageIntelligenceAgency;
+    private ConcurrentHashMap<NodeId, ServiceChangeListener> serviceChangeListeners = new ConcurrentHashMap<>();
+
+    public LifecycleConductorImpl(final MessageIntelligenceAgency messageIntelligenceAgency) {
+        Preconditions.checkNotNull(messageIntelligenceAgency);
+        this.messageIntelligenceAgency = messageIntelligenceAgency;
+    }
+
+    public void setSafelyDeviceManager(final DeviceManager deviceManager) {
+        if (this.deviceManager == null) {
+            this.deviceManager = deviceManager;
+        }
+    }
+
+    public void addOneTimeListenerWhenServicesChangesDone(final ServiceChangeListener manager, final NodeId nodeId){
+        LOG.debug("Listener {} for service change for node {} registered.", manager, nodeId);
+        serviceChangeListeners.put(nodeId, manager);
+    }
+
+    private void notifyServiceChangeListeners(final NodeId nodeId, final boolean success){
+        if (serviceChangeListeners.size() == 0) {
+            return;
+        }
+        LOG.debug("Notifying registered listeners for service change, no. of listeners {}", serviceChangeListeners.size());
+        for (final Map.Entry<NodeId, ServiceChangeListener> nodeIdServiceChangeListenerEntry : serviceChangeListeners.entrySet()) {
+            if (nodeIdServiceChangeListenerEntry.getKey().equals(nodeId)) {
+                LOG.debug("Listener {} for service change for node {} was notified. Success was set on {}", nodeIdServiceChangeListenerEntry.getValue(), nodeId, success);
+                nodeIdServiceChangeListenerEntry.getValue().servicesChangeDone(nodeId, success);
+                serviceChangeListeners.remove(nodeId);
+            }
+        }
+    }
+
+    @Override
+    public void roleInitializationDone(final NodeId nodeId, final boolean success) {
+        if (!success) {
+            LOG.warn("Initialization phase for node {} in role context was NOT successful, closing connection.", nodeId);
+            closeConnection(nodeId);
+        } else {
+            LOG.info("initialization phase for node {} in role context was successful, continuing to next context.", nodeId);
+        }
+    }
+
+    public void closeConnection(final NodeId nodeId) {
+        LOG.debug("Close connection called for node {}", nodeId);
+        final DeviceContext deviceContext = getDeviceContext(nodeId);
+        if (null != deviceContext) {
+            deviceContext.shutdownConnection();
+        }
+    }
+
+    @Override
+    public void roleChangeOnDevice(final NodeId nodeId, final boolean success, final OfpRole newRole, final boolean initializationPhase) {
+
+        final DeviceContext deviceContext = getDeviceContext(nodeId);
+
+        if (null == deviceContext) {
+            LOG.warn("Something went wrong, device context for nodeId: {} doesn't exists");
+            return;
+        }
+        if (!success) {
+            LOG.warn("Role change to {} in role context for node {} was NOT successful, closing connection", newRole, nodeId);
+            closeConnection(nodeId);
+        } else {
+            if (initializationPhase) {
+                LOG.debug("Initialization phase skipping starting services.");
+                return;
+            }
+            LOG.info("Role change to {} in role context for node {} was successful, staring/stopping services.", newRole, nodeId);
+
+            //TODO: This is old way to check if statistics is running, remove after statistics changes implemented
+            final DeviceState deviceState = deviceContext.getDeviceState();
+            if (null != deviceState) {
+                if (OfpRole.BECOMEMASTER.equals(newRole) && (getDeviceContext(nodeId) != null)) {
+                    deviceState.setRole(OfpRole.BECOMEMASTER);
+                } else {
+                    deviceState.setRole(OfpRole.BECOMESLAVE);
+                }
+            }
+
+            final ListenableFuture<Void> onClusterRoleChange = deviceContext.onClusterRoleChange(null, newRole);
+            Futures.addCallback(onClusterRoleChange, new FutureCallback<Void>() {
+                @Override
+                public void onSuccess(@Nullable final Void aVoid) {
+                    LOG.info("Starting/Stopping services for node {} was successful", nodeId);
+                    if (newRole.equals(OfpRole.BECOMESLAVE)) notifyServiceChangeListeners(nodeId, true);
+                }
+
+                @Override
+                public void onFailure(final Throwable throwable) {
+                    LOG.warn("Starting/Stopping services for node {} was NOT successful, closing connection", nodeId);
+                    closeConnection(nodeId);
+                }
+            });
+        }
+    }
+
+    public MessageIntelligenceAgency getMessageIntelligenceAgency() {
+        return messageIntelligenceAgency;
+    }
+
+    @Override
+    public DeviceContext getDeviceContext(final NodeId nodeId){
+         return deviceManager.getDeviceContextFromNodeId(nodeId);
+    }
+
+    public Short gainVersionSafely(final NodeId nodeId) {
+        return (null != getDeviceContext(nodeId)) ? getDeviceContext(nodeId).getPrimaryConnectionContext().getFeatures().getVersion() : null;
+    }
+
+    public Timeout newTimeout(@Nonnull TimerTask task, long delay, @Nonnull TimeUnit unit) {
+        return hashedWheelTimer.newTimeout(task, delay, unit);
+    }
+
+    public ConnectionContext.CONNECTION_STATE gainConnectionStateSafely(final NodeId nodeId){
+        return (null != getDeviceContext(nodeId)) ? getDeviceContext(nodeId).getPrimaryConnectionContext().getConnectionState() : null;
+    }
+
+    public Long reserveXidForDeviceMessage(final NodeId nodeId){
+        return null != getDeviceContext(nodeId) ? getDeviceContext(nodeId).reserveXidForDeviceMessage() : null;
+    }
+
+    @Override
+    public void deviceStartInitializationDone(final NodeId nodeId, final boolean success) {
+        if (!success) {
+            LOG.warn("Initialization phase for node {} in device context was NOT successful, closing connection.", nodeId);
+            closeConnection(nodeId);
+        } else {
+            LOG.info("initialization phase for node {} in device context was successful. Continuing to next context.", nodeId);
+        }
+    }
+
+    @Override
+    public void deviceInitializationDone(final NodeId nodeId, final boolean success) {
+        if (!success) {
+            LOG.warn("Initialization phase for node {} in device context was NOT successful, closing connection.", nodeId);
+            closeConnection(nodeId);
+        } else {
+            LOG.info("initialization phase for node {} in device context was successful. All phases initialized OK.", nodeId);
+        }
+    }
+}
index d1fa7e59a04f5ad39cf297810f3ee57a0eaf7e6a..84120ddc383c8da20a3bcb3d2e7bb42a4a2aa28d 100644 (file)
@@ -17,6 +17,7 @@ import java.lang.management.ManagementFactory;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.List;
+import javax.annotation.Nonnull;
 import javax.management.InstanceAlreadyExistsException;
 import javax.management.MBeanRegistrationException;
 import javax.management.MBeanServer;
@@ -32,6 +33,8 @@ import org.opendaylight.openflowjava.protocol.spi.connection.SwitchConnectionPro
 import org.opendaylight.openflowplugin.api.openflow.OpenFlowPluginProvider;
 import org.opendaylight.openflowplugin.api.openflow.connection.ConnectionManager;
 import org.opendaylight.openflowplugin.api.openflow.device.DeviceManager;
+import org.opendaylight.openflowplugin.api.openflow.lifecycle.LifecycleConductor;
+import org.opendaylight.openflowplugin.api.openflow.lifecycle.RoleChangeListener;
 import org.opendaylight.openflowplugin.api.openflow.role.RoleManager;
 import org.opendaylight.openflowplugin.api.openflow.rpc.RpcManager;
 import org.opendaylight.openflowplugin.api.openflow.statistics.StatisticsManager;
@@ -53,9 +56,6 @@ import org.opendaylight.openflowplugin.openflow.md.core.session.OFSessionUtil;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-/**
- * Created by Martin Bobak &lt;mbobak@cisco.com&gt; on 27.3.2015.
- */
 public class OpenFlowPluginProviderImpl implements OpenFlowPluginProvider, OpenFlowPluginExtensionRegistratorProvider {
 
     private static final Logger LOG = LoggerFactory.getLogger(OpenFlowPluginProviderImpl.class);
@@ -84,10 +84,13 @@ public class OpenFlowPluginProviderImpl implements OpenFlowPluginProvider, OpenF
     private boolean isStatisticsPollingOff = false;
     private boolean isStatisticsRpcEnabled;
 
+    private final LifecycleConductor conductor;
+
     public OpenFlowPluginProviderImpl(final long rpcRequestsQuota, final Long globalNotificationQuota) {
         Preconditions.checkArgument(rpcRequestsQuota > 0 && rpcRequestsQuota <= Integer.MAX_VALUE, "rpcRequestQuota has to be in range <1,%s>", Integer.MAX_VALUE);
         this.rpcRequestsQuota = (int) rpcRequestsQuota;
         this.globalNotificationQuota = Preconditions.checkNotNull(globalNotificationQuota);
+        conductor = new LifecycleConductorImpl(messageIntelligenceAgency);
     }
 
     @Override
@@ -117,7 +120,7 @@ public class OpenFlowPluginProviderImpl implements OpenFlowPluginProvider, OpenF
             }
 
             @Override
-            public void onFailure(final Throwable t) {
+            public void onFailure(@Nonnull final Throwable t) {
                 LOG.warn("Some switchConnectionProviders failed to start.", t);
             }
         });
@@ -189,12 +192,21 @@ public class OpenFlowPluginProviderImpl implements OpenFlowPluginProvider, OpenF
 
         registerMXBean(messageIntelligenceAgency);
 
-        deviceManager = new DeviceManagerImpl(dataBroker, messageIntelligenceAgency, globalNotificationQuota,
-                switchFeaturesMandatory, barrierInterval, barrierCountLimit);
+        deviceManager = new DeviceManagerImpl(dataBroker,
+                globalNotificationQuota,
+                switchFeaturesMandatory,
+                barrierInterval,
+                barrierCountLimit,
+                conductor);
         ((ExtensionConverterProviderKeeper) deviceManager).setExtensionConverterProvider(extensionConverterManager);
-        roleManager = new RoleManagerImpl(entityOwnershipService, dataBroker);
-        statisticsManager = new StatisticsManagerImpl(rpcProviderRegistry, isStatisticsPollingOff);
-        rpcManager = new RpcManagerImpl(rpcProviderRegistry, rpcRequestsQuota);
+
+        conductor.setSafelyDeviceManager(deviceManager);
+
+        roleManager = new RoleManagerImpl(entityOwnershipService, dataBroker, conductor);
+        statisticsManager = new StatisticsManagerImpl(rpcProviderRegistry, isStatisticsPollingOff, conductor);
+        rpcManager = new RpcManagerImpl(rpcProviderRegistry, rpcRequestsQuota, conductor);
+
+        roleManager.addRoleChangeListener((RoleChangeListener) conductor);
 
         /* Initialization Phase ordering - OFP Device Context suite */
         // CM -> DM -> SM -> RPC -> Role -> DM
@@ -210,11 +222,8 @@ public class OpenFlowPluginProviderImpl implements OpenFlowPluginProvider, OpenF
         statisticsManager.setDeviceTerminationPhaseHandler(roleManager);
         roleManager.setDeviceTerminationPhaseHandler(deviceManager);
 
-        rpcManager.setStatisticsRpcEnabled(isStatisticsRpcEnabled);
-        rpcManager.setNotificationPublishService(notificationPublishService);
-
-        deviceManager.setNotificationService(this.notificationProviderService);
-        deviceManager.setNotificationPublishService(this.notificationPublishService);
+        deviceManager.setStatisticsRpcEnabled(isStatisticsRpcEnabled);
+        deviceManager.setNotificationPublishService(notificationPublishService);
 
         TranslatorLibraryUtil.setBasicTranslatorLibrary(deviceManager);
         deviceManager.initialize();
index 3fecb793c5dbb63deb6d838f947b75c12af04e1b..a0a20a9a00d3f308310642f7542f8dee828067e3 100644 (file)
@@ -10,6 +10,13 @@ package org.opendaylight.openflowplugin.impl.connection;
 
 import java.math.BigInteger;
 import java.net.InetSocketAddress;
+import java.util.concurrent.Callable;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+
 import org.opendaylight.openflowjava.protocol.api.connection.ConnectionAdapter;
 import org.opendaylight.openflowjava.protocol.api.connection.OutboundQueue;
 import org.opendaylight.openflowjava.protocol.api.connection.OutboundQueueHandlerRegistration;
@@ -91,7 +98,7 @@ public class ConnectionContextImpl implements ConnectionContext {
     }
 
     @Override
-    public void closeConnection(boolean propagate) {
+    public void closeConnection(final boolean propagate) {
         if (null == nodeId){
             SessionStatistics.countEvent(connectionAdapter.getRemoteAddress().toString(), SessionStatistics.ConnectionStatus.CONNECTION_DISCONNECTED_BY_OFP);
         } else {
@@ -102,7 +109,25 @@ public class ConnectionContextImpl implements ConnectionContext {
                 connectionAdapter.getRemoteAddress(), datapathId);
         connectionState = ConnectionContext.CONNECTION_STATE.RIP;
 
-        unregisterOutboundQueue();
+        Future<Void> future = Executors.newSingleThreadExecutor().submit(new Callable<Void>() {
+            @Override
+            public Void call() throws Exception {
+                unregisterOutboundQueue();
+                return null;
+            }
+        });
+        try {
+            LOG.debug("Waiting 1s for unregistering outbound queue.");
+            future.get(1, TimeUnit.SECONDS);
+            LOG.info("Unregistering outbound queue successful.");
+        } catch (InterruptedException e) {
+            LOG.warn("Unregistering outbound queue was interrupted for node {}", nodeId);
+        } catch (ExecutionException e) {
+            LOG.warn("Unregistering outbound queue throws exception for node {}", nodeId, e);
+        } catch (TimeoutException e) {
+            LOG.warn("Unregistering outbound queue took longer than 1 seconds for node {}", nodeId);
+        }
+
         closeHandshakeContext();
 
         if (getConnectionAdapter().isAlive()) {
@@ -110,11 +135,15 @@ public class ConnectionContextImpl implements ConnectionContext {
         }
 
         if (propagate) {
+            LOG.debug("Propagating device disconnect for node {}", nodeId);
             propagateDeviceDisconnectedEvent();
+        } else {
+            LOG.debug("Close connection without propagating for node {}", nodeId);
         }
     }
 
     private void closeHandshakeContext() {
+        LOG.debug("Trying closing handshake context for node {}", nodeId);
         if (handshakeContext != null) {
             try {
                 handshakeContext.close();
@@ -168,6 +197,7 @@ public class ConnectionContextImpl implements ConnectionContext {
     }
 
     private void unregisterOutboundQueue() {
+        LOG.debug("Trying unregister outbound queue handler registration for node {}", nodeId);
         if (outboundQueueHandlerRegistration != null) {
             outboundQueueHandlerRegistration.close();
             outboundQueueHandlerRegistration = null;
index f1c7a9a2e41ed3930e118d7ef2df2357a66eb7da..037dc200f9f37e092d10aecdb4da309b145fb94a 100644 (file)
@@ -62,7 +62,9 @@ public class HandshakeListenerImpl implements HandshakeListener {
             public void onSuccess(@Nullable final RpcResult<BarrierOutput> result) {
                 LOG.debug("succeeded by getting sweep barrier after posthandshake for device {}", connectionContext.getNodeId());
                 try {
-                    deviceConnectedHandler.deviceConnected(connectionContext);
+                    if (!deviceConnectedHandler.deviceConnected(connectionContext)) {
+                        connectionContext.closeConnection(true);
+                    }
                     SessionStatistics.countEvent(connectionContext.getNodeId().toString(),
                             SessionStatistics.ConnectionStatus.CONNECTION_CREATED);
                 } catch (final Exception e) {
index 800fa9cfa7933a3e2458bba4c382c22f9279e708..17a86f0c12e18016638ab67f8e102ae37a1ad1ff 100644 (file)
@@ -11,29 +11,21 @@ import com.google.common.annotations.VisibleForTesting;
 import com.google.common.base.Function;
 import com.google.common.base.Preconditions;
 import com.google.common.base.Verify;
-import com.google.common.collect.Iterators;
 import com.google.common.util.concurrent.AsyncFunction;
 import com.google.common.util.concurrent.FutureCallback;
-import com.google.common.util.concurrent.FutureFallback;
 import com.google.common.util.concurrent.Futures;
 import com.google.common.util.concurrent.ListenableFuture;
-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.HashMap;
-import java.util.HashSet;
-import java.util.LinkedList;
-import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
 import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.atomic.AtomicLong;
 import javax.annotation.CheckForNull;
 import javax.annotation.Nonnull;
 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
 import org.opendaylight.controller.md.sal.binding.api.NotificationPublishService;
-import org.opendaylight.controller.md.sal.binding.api.NotificationService;
 import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
 import org.opendaylight.openflowjava.protocol.api.connection.ConnectionAdapter;
@@ -47,7 +39,6 @@ import org.opendaylight.openflowplugin.api.openflow.device.MessageTranslator;
 import org.opendaylight.openflowplugin.api.openflow.device.RequestContext;
 import org.opendaylight.openflowplugin.api.openflow.device.TranslatorLibrary;
 import org.opendaylight.openflowplugin.api.openflow.device.Xid;
-import org.opendaylight.openflowplugin.api.openflow.device.handlers.DeviceTerminationPhaseHandler;
 import org.opendaylight.openflowplugin.api.openflow.device.handlers.MultiMsgCollector;
 import org.opendaylight.openflowplugin.api.openflow.md.core.SwitchConnectionDistinguisher;
 import org.opendaylight.openflowplugin.api.openflow.md.core.TranslatorKey;
@@ -74,6 +65,7 @@ import org.opendaylight.openflowplugin.impl.registry.flow.DeviceFlowRegistryImpl
 import org.opendaylight.openflowplugin.impl.registry.flow.FlowRegistryKeyFactory;
 import org.opendaylight.openflowplugin.impl.registry.group.DeviceGroupRegistryImpl;
 import org.opendaylight.openflowplugin.impl.registry.meter.DeviceMeterRegistryImpl;
+import org.opendaylight.openflowplugin.impl.rpc.RpcContextImpl;
 import org.opendaylight.openflowplugin.impl.util.DeviceInitializationUtils;
 import org.opendaylight.openflowplugin.impl.util.MdSalRegistrationUtils;
 import org.opendaylight.openflowplugin.openflow.md.core.session.SwitchConnectionCookieOFImpl;
@@ -85,6 +77,7 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.ta
 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.FlowKey;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorId;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeConnectorRef;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRef;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnector;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.node.NodeConnectorBuilder;
@@ -120,7 +113,7 @@ public class DeviceContextImpl implements DeviceContext, ExtensionConverterProvi
     private static final Logger LOG = LoggerFactory.getLogger(DeviceContextImpl.class);
 
     // TODO: drain factor should be parametrized
-    public static final float REJECTED_DRAIN_FACTOR = 0.25f;
+    private static final float REJECTED_DRAIN_FACTOR = 0.25f;
     // TODO: low water mark factor should be parametrized
     private static final float LOW_WATERMARK_FACTOR = 0.75f;
     // TODO: high water mark factor should be parametrized
@@ -129,18 +122,15 @@ public class DeviceContextImpl implements DeviceContext, ExtensionConverterProvi
     private final ConnectionContext primaryConnectionContext;
     private final DeviceState deviceState;
     private final DataBroker dataBroker;
-    private final HashedWheelTimer hashedWheelTimer;
     private final Map<SwitchConnectionDistinguisher, ConnectionContext> auxiliaryConnectionContexts;
     private final TransactionChainManager transactionChainManager;
     private final DeviceFlowRegistry deviceFlowRegistry;
     private final DeviceGroupRegistry deviceGroupRegistry;
     private final DeviceMeterRegistry deviceMeterRegistry;
-    private final Collection<DeviceTerminationPhaseHandler> closeHandlers = new HashSet<>();
     private final PacketInRateLimiter packetInLimiter;
     private final MessageSpy messageSpy;
     private final ItemLifeCycleKeeper flowLifeCycleKeeper;
     private NotificationPublishService notificationPublishService;
-    private NotificationService notificationService;
     private final OutboundQueue outboundQueueProvider;
     private Timeout barrierTaskTimeout;
     private final MessageTranslator<PortGrouping, FlowCapableNodeConnector> portStatusTranslator;
@@ -155,14 +145,16 @@ public class DeviceContextImpl implements DeviceContext, ExtensionConverterProvi
     private final boolean switchFeaturesMandatory;
     private StatisticsContext statisticsContext;
 
+    private final NodeId nodeId;
+
     private volatile DEVICE_CONTEXT_STATE deviceCtxState;
+    private boolean isStatisticsRpcEnabled;
 
 
     @VisibleForTesting
     DeviceContextImpl(@Nonnull final ConnectionContext primaryConnectionContext,
                       @Nonnull final DeviceState deviceState,
                       @Nonnull final DataBroker dataBroker,
-                      @Nonnull final HashedWheelTimer hashedWheelTimer,
                       @Nonnull final MessageSpy _messageSpy,
                       @Nonnull final OutboundQueueProvider outboundQueueProvider,
                       @Nonnull final TranslatorLibrary translatorLibrary,
@@ -171,7 +163,6 @@ public class DeviceContextImpl implements DeviceContext, ExtensionConverterProvi
         this.primaryConnectionContext = Preconditions.checkNotNull(primaryConnectionContext);
         this.deviceState = Preconditions.checkNotNull(deviceState);
         this.dataBroker = Preconditions.checkNotNull(dataBroker);
-        this.hashedWheelTimer = Preconditions.checkNotNull(hashedWheelTimer);
         this.outboundQueueProvider = Preconditions.checkNotNull(outboundQueueProvider);
         this.transactionChainManager = new TransactionChainManager(dataBroker, deviceState);
         auxiliaryConnectionContexts = new HashMap<>();
@@ -198,6 +189,8 @@ public class DeviceContextImpl implements DeviceContext, ExtensionConverterProvi
         flowLifeCycleKeeper = new ItemLifeCycleSourceImpl();
         itemLifeCycleSourceRegistry.registerLifeCycleSource(flowLifeCycleKeeper);
         deviceCtxState = DEVICE_CONTEXT_STATE.INITIALIZATION;
+
+        nodeId = primaryConnectionContext.getNodeId();
     }
 
     /**
@@ -209,7 +202,7 @@ public class DeviceContextImpl implements DeviceContext, ExtensionConverterProvi
     }
 
     @Override
-    public Long reservedXidForDeviceMessage() {
+    public Long reserveXidForDeviceMessage() {
         return outboundQueueProvider.reserveEntry();
     }
 
@@ -226,11 +219,9 @@ public class DeviceContextImpl implements DeviceContext, ExtensionConverterProvi
     @Override
     public void removeAuxiliaryConnectionContext(final ConnectionContext connectionContext) {
         final SwitchConnectionDistinguisher connectionDistinguisher = createConnectionDistinguisher(connectionContext);
-        if (null != connectionDistinguisher) {
-            LOG.debug("auxiliary connection dropped: {}, nodeId:{}", connectionContext.getConnectionAdapter()
-                    .getRemoteAddress(), getDeviceState().getNodeId());
-            auxiliaryConnectionContexts.remove(connectionDistinguisher);
-        }
+        LOG.debug("auxiliary connection dropped: {}, nodeId:{}", connectionContext.getConnectionAdapter()
+                .getRemoteAddress(), nodeId);
+        auxiliaryConnectionContexts.remove(connectionDistinguisher);
     }
 
     @Override
@@ -245,10 +236,10 @@ public class DeviceContextImpl implements DeviceContext, ExtensionConverterProvi
 
     @Override
     public ListenableFuture<Void> onClusterRoleChange(final OfpRole oldRole, @CheckForNull final OfpRole role) {
-        LOG.trace("onClusterRoleChange {} for node:", role, deviceState.getNodeId());
+        LOG.trace("onClusterRoleChange {} for node:", role, nodeId);
         Preconditions.checkArgument(role != null);
         if (role.equals(oldRole)) {
-            LOG.debug("Demanded role change for device {} is not changed. OldRole: {}, NewRole {}", deviceState.getNodeId(), oldRole, role);
+            LOG.debug("Demanded role change for device {} is not changed. OldRole: {}, NewRole {}", nodeId, oldRole, role);
             return Futures.immediateFuture(null);
         }
         if (OfpRole.BECOMEMASTER.equals(role)) {
@@ -256,7 +247,7 @@ public class DeviceContextImpl implements DeviceContext, ExtensionConverterProvi
         } else if (OfpRole.BECOMESLAVE.equals(role)) {
             return onDeviceLostClusterLeadership();
         } else {
-            LOG.warn("Unknown OFCluster Role {} for Node {}", role, deviceState.getNodeId());
+            LOG.warn("Unknown OFCluster Role {} for Node {}", role, nodeId);
             if (null != rpcContext) {
                 MdSalRegistrationUtils.unregisterServices(rpcContext);
             }
@@ -266,7 +257,7 @@ public class DeviceContextImpl implements DeviceContext, ExtensionConverterProvi
 
     @Override
     public ListenableFuture<Void> onDeviceLostClusterLeadership() {
-        LOG.trace("onDeviceLostClusterLeadership for node: {}", deviceState.getNodeId());
+        LOG.trace("onDeviceLostClusterLeadership for node: {}", nodeId);
         if (null != rpcContext) {
             MdSalRegistrationUtils.registerSlaveServices(rpcContext, OfpRole.BECOMESLAVE);
         }
@@ -275,21 +266,25 @@ public class DeviceContextImpl implements DeviceContext, ExtensionConverterProvi
 
     @Override
     public ListenableFuture<Void> onDeviceTakeClusterLeadership() {
-        LOG.trace("onDeviceTakeClusterLeadership for node: {}", deviceState.getNodeId());
+        LOG.trace("onDeviceTakeClusterLeadership for node: {}", nodeId);
         /* validation */
         if (statisticsContext == null) {
-            final String errMsg = String.format("DeviceCtx %s is up but we are missing StatisticsContext", deviceState.getNodeId());
+            final String errMsg = String.format("DeviceCtx %s is up but we are missing StatisticsContext", nodeId);
             LOG.warn(errMsg);
             return Futures.immediateFailedFuture(new IllegalStateException(errMsg));
         }
         if (rpcContext == null) {
-            final String errMsg = String.format("DeviceCtx %s is up but we are missing RpcContext", deviceState.getNodeId());
+            final String errMsg = String.format("DeviceCtx %s is up but we are missing RpcContext", nodeId);
             LOG.warn(errMsg);
             return Futures.immediateFailedFuture(new IllegalStateException(errMsg));
         }
         /* Routed RPC registration */
         MdSalRegistrationUtils.registerMasterServices(getRpcContext(), DeviceContextImpl.this, OfpRole.BECOMEMASTER);
-        getRpcContext().registerStatCompatibilityServices();
+
+        if (isStatisticsRpcEnabled) {
+            MdSalRegistrationUtils.registerStatCompatibilityServices(getRpcContext(), this,
+                    notificationPublishService, new AtomicLong());
+        }
 
         /* Prepare init info collecting */
         getDeviceState().setDeviceSynchronized(false);
@@ -302,7 +297,7 @@ public class DeviceContextImpl implements DeviceContext, ExtensionConverterProvi
                 new AsyncFunction<Void, Boolean>() {
 
                     @Override
-                    public ListenableFuture<Boolean> apply(final Void input) throws Exception {
+                    public ListenableFuture<Boolean> apply(@Nonnull final Void input) throws Exception {
                         getStatisticsContext().statListForCollectingInitialization();
                         return getStatisticsContext().gatherDynamicData();
                     }
@@ -318,13 +313,13 @@ public class DeviceContextImpl implements DeviceContext, ExtensionConverterProvi
                     LOG.warn(errMsg);
                     throw new IllegalStateException(errMsg);
                 }
-                if (!input.booleanValue()) {
+                if (!input) {
                     final String errMsg = String.format("Get Initial Device %s information fails",
                             getDeviceState().getNodeId());
                     LOG.warn(errMsg);
                     throw new IllegalStateException(errMsg);
                 }
-                LOG.debug("Get Initial Device {} information is successful", getDeviceState().getNodeId());
+                LOG.debug("Get Initial Device {} information is successful", nodeId);
                 getDeviceState().setDeviceSynchronized(true);
                 initialSubmitTransaction();
                 getDeviceState().setStatisticsPollingEnabledProp(true);
@@ -335,12 +330,12 @@ public class DeviceContextImpl implements DeviceContext, ExtensionConverterProvi
 
     @Override
     public <T extends DataObject> void writeToTransaction(final LogicalDatastoreType store,
-                                                          final InstanceIdentifier<T> path, final T data) {
+                                                          final InstanceIdentifier<T> path, final T data) throws Exception {
         transactionChainManager.writeToTransaction(store, path, data);
     }
 
     @Override
-    public <T extends DataObject> void addDeleteToTxChain(final LogicalDatastoreType store, final InstanceIdentifier<T> path) {
+    public <T extends DataObject> void addDeleteToTxChain(final LogicalDatastoreType store, final InstanceIdentifier<T> path) throws Exception {
         transactionChainManager.addDeleteOperationTotTxChain(store, path);
     }
 
@@ -423,16 +418,20 @@ public class DeviceContextImpl implements DeviceContext, ExtensionConverterProvi
         final FlowCapableNodeConnector flowCapableNodeConnector = portStatusTranslator.translate(portStatus, this, null);
 
         final KeyedInstanceIdentifier<NodeConnector, NodeConnectorKey> iiToNodeConnector = provideIIToNodeConnector(portStatus.getPortNo(), portStatus.getVersion());
-        if (portStatus.getReason().equals(PortReason.OFPPRADD) || portStatus.getReason().equals(PortReason.OFPPRMODIFY)) {
-            // because of ADD status node connector has to be created
-            final NodeConnectorBuilder nConnectorBuilder = new NodeConnectorBuilder().setKey(iiToNodeConnector.getKey());
-            nConnectorBuilder.addAugmentation(FlowCapableNodeConnectorStatisticsData.class, new FlowCapableNodeConnectorStatisticsDataBuilder().build());
-            nConnectorBuilder.addAugmentation(FlowCapableNodeConnector.class, flowCapableNodeConnector);
-            writeToTransaction(LogicalDatastoreType.OPERATIONAL, iiToNodeConnector, nConnectorBuilder.build());
-        } else if (portStatus.getReason().equals(PortReason.OFPPRDELETE)) {
-            addDeleteToTxChain(LogicalDatastoreType.OPERATIONAL, iiToNodeConnector);
+        try {
+            if (portStatus.getReason().equals(PortReason.OFPPRADD) || portStatus.getReason().equals(PortReason.OFPPRMODIFY)) {
+                // because of ADD status node connector has to be created
+                final NodeConnectorBuilder nConnectorBuilder = new NodeConnectorBuilder().setKey(iiToNodeConnector.getKey());
+                nConnectorBuilder.addAugmentation(FlowCapableNodeConnectorStatisticsData.class, new FlowCapableNodeConnectorStatisticsDataBuilder().build());
+                nConnectorBuilder.addAugmentation(FlowCapableNodeConnector.class, flowCapableNodeConnector);
+                writeToTransaction(LogicalDatastoreType.OPERATIONAL, iiToNodeConnector, nConnectorBuilder.build());
+            } else if (portStatus.getReason().equals(PortReason.OFPPRDELETE)) {
+                addDeleteToTxChain(LogicalDatastoreType.OPERATIONAL, iiToNodeConnector);
+            }
+            submitTransaction();
+        } catch (final Exception e) {
+            LOG.warn("Error processing port status message: {}", e.getMessage());
         }
-        submitTransaction();
     }
 
     private KeyedInstanceIdentifier<NodeConnector, NodeConnectorKey> provideIIToNodeConnector(final long portNo, final short version) {
@@ -463,7 +462,7 @@ public class DeviceContextImpl implements DeviceContext, ExtensionConverterProvi
             return;
         }
 
-        final ListenableFuture<? extends Object> offerNotification = notificationPublishService.offerNotification(packetReceived);
+        final ListenableFuture<?> offerNotification = notificationPublishService.offerNotification(packetReceived);
         if (NotificationPublishService.REJECTED.equals(offerNotification)) {
             LOG.debug("notification offer rejected");
             messageSpy.spyMessage(packetReceived.getImplementedInterface(), MessageSpy.STATISTIC_GROUP.FROM_SWITCH_NOTIFICATION_REJECTED);
@@ -522,11 +521,6 @@ public class DeviceContextImpl implements DeviceContext, ExtensionConverterProvi
         return translatorLibrary;
     }
 
-    @Override
-    public HashedWheelTimer getTimer() {
-        return hashedWheelTimer;
-    }
-
     @Override
     public synchronized void close() {
         LOG.debug("closing deviceContext: {}, nodeId:{}",
@@ -546,11 +540,6 @@ public class DeviceContextImpl implements DeviceContext, ExtensionConverterProvi
         return barrierTaskTimeout;
     }
 
-    @Override
-    public void setNotificationService(final NotificationService notificationService) {
-        this.notificationService = notificationService;
-    }
-
     @Override
     public void setNotificationPublishService(final NotificationPublishService notificationPublishService) {
         this.notificationPublishService = notificationPublishService;
@@ -561,11 +550,6 @@ public class DeviceContextImpl implements DeviceContext, ExtensionConverterProvi
         return messageSpy;
     }
 
-    @Override
-    public void addDeviceContextClosedHandler(final DeviceTerminationPhaseHandler deviceContextClosedHandler) {
-        closeHandlers.add(deviceContextClosedHandler);
-    }
-
     @Override
     public void onPublished() {
         Verify.verify(DEVICE_CONTEXT_STATE.INITIALIZATION.equals(deviceCtxState));
@@ -587,7 +571,7 @@ public class DeviceContextImpl implements DeviceContext, ExtensionConverterProvi
     }
 
     @Override
-    public void storeNodeConnectorRef(final Long portNumber, final NodeConnectorRef nodeConnectorRef) {
+    public void storeNodeConnectorRef(@Nonnull final Long portNumber, @Nonnull final NodeConnectorRef nodeConnectorRef) {
         nodeConnectorCache.put(
                 Preconditions.checkNotNull(portNumber),
                 Preconditions.checkNotNull(nodeConnectorRef));
@@ -635,23 +619,21 @@ public class DeviceContextImpl implements DeviceContext, ExtensionConverterProvi
 
     @Override
     public synchronized void shutdownConnection() {
-        LOG.trace("shutdown method for node {}", deviceState.getNodeId());
+        LOG.debug("Shutdown method for node {}", nodeId);
         deviceState.setValid(false);
         if (DEVICE_CONTEXT_STATE.TERMINATION.equals(deviceCtxState)) {
-            LOG.debug("DeviceCtx for Node {} is in termination process.", deviceState.getNodeId());
+            LOG.debug("DeviceCtx for Node {} is in termination process.", nodeId);
             return;
         }
         deviceCtxState = DEVICE_CONTEXT_STATE.TERMINATION;
-        for (final Iterator<ConnectionContext> iterator = Iterators.consumingIterator(auxiliaryConnectionContexts
-                .values().iterator()); iterator.hasNext();) {
-            iterator.next().closeConnection(false);
-        }
+
         if (ConnectionContext.CONNECTION_STATE.RIP.equals(getPrimaryConnectionContext().getConnectionState())) {
             LOG.debug("ConnectionCtx for Node {} is in RIP state.", deviceState.getNodeId());
             return;
         }
         /* Terminate Auxiliary Connection */
         for (final ConnectionContext connectionContext : auxiliaryConnectionContexts.values()) {
+            LOG.debug("Closing auxiliary connection {}", connectionContext.getNodeId());
             connectionContext.closeConnection(false);
         }
         /* Terminate Primary Connection */
@@ -662,6 +644,11 @@ public class DeviceContextImpl implements DeviceContext, ExtensionConverterProvi
         deviceMeterRegistry.close();
     }
 
+    @Override
+    public void setStatisticsRpcEnabled(boolean isStatisticsRpcEnabled) {
+        this.isStatisticsRpcEnabled = isStatisticsRpcEnabled;
+    }
+
     @Override
     public DEVICE_CONTEXT_STATE getDeviceContextState() {
         return deviceCtxState;
index 7fc078ccd4ec76b3feca7d9cd5cac18a0f970c85..4eb33295a200f781d5366fd3d7e1975ae8df5447 100644 (file)
@@ -7,13 +7,13 @@
  */
 package org.opendaylight.openflowplugin.impl.device;
 
+import com.google.common.annotations.VisibleForTesting;
 import com.google.common.base.Preconditions;
 import com.google.common.base.Verify;
 import com.google.common.collect.Iterators;
 import com.google.common.util.concurrent.FutureCallback;
 import com.google.common.util.concurrent.Futures;
 import com.google.common.util.concurrent.ListenableFuture;
-import io.netty.util.HashedWheelTimer;
 import io.netty.util.Timeout;
 import io.netty.util.TimerTask;
 import java.util.Collections;
@@ -40,7 +40,7 @@ import org.opendaylight.openflowplugin.api.openflow.device.DeviceState;
 import org.opendaylight.openflowplugin.api.openflow.device.TranslatorLibrary;
 import org.opendaylight.openflowplugin.api.openflow.device.handlers.DeviceInitializationPhaseHandler;
 import org.opendaylight.openflowplugin.api.openflow.device.handlers.DeviceTerminationPhaseHandler;
-import org.opendaylight.openflowplugin.api.openflow.statistics.ofpspecific.MessageIntelligenceAgency;
+import org.opendaylight.openflowplugin.api.openflow.lifecycle.LifecycleConductor;
 import org.opendaylight.openflowplugin.extension.api.ExtensionConverterProviderKeeper;
 import org.opendaylight.openflowplugin.extension.api.core.extension.ExtensionConverterProvider;
 import org.opendaylight.openflowplugin.impl.connection.OutboundQueueProviderImpl;
@@ -60,36 +60,34 @@ public class DeviceManagerImpl implements DeviceManager, ExtensionConverterProvi
 
     private static final Logger LOG = LoggerFactory.getLogger(DeviceManagerImpl.class);
 
-    private static final long TICK_DURATION = 10; // 0.5 sec.
     private final long globalNotificationQuota;
     private final boolean switchFeaturesMandatory;
 
-    private ScheduledThreadPoolExecutor spyPool;
     private final int spyRate = 10;
 
     private final DataBroker dataBroker;
-    private final HashedWheelTimer hashedWheelTimer;
     private TranslatorLibrary translatorLibrary;
     private DeviceInitializationPhaseHandler deviceInitPhaseHandler;
     private DeviceTerminationPhaseHandler deviceTerminPhaseHandler;
-    private NotificationService notificationService;
     private NotificationPublishService notificationPublishService;
 
     private final ConcurrentMap<NodeId, DeviceContext> deviceContexts = new ConcurrentHashMap<>();
-    private final MessageIntelligenceAgency messageIntelligenceAgency;
 
     private final long barrierIntervalNanos;
     private final int barrierCountLimit;
     private ExtensionConverterProvider extensionConverterProvider;
+    private ScheduledThreadPoolExecutor spyPool;
+
+    private final LifecycleConductor conductor;
+    private boolean isStatisticsRpcEnabled;
 
     public DeviceManagerImpl(@Nonnull final DataBroker dataBroker,
-                             @Nonnull final MessageIntelligenceAgency messageIntelligenceAgency,
                              final long globalNotificationQuota, final boolean switchFeaturesMandatory,
-                             final long barrierInterval, final int barrierCountLimit) {
+                             final long barrierInterval, final int barrierCountLimit,
+                             final LifecycleConductor lifecycleConductor) {
         this.switchFeaturesMandatory = switchFeaturesMandatory;
         this.globalNotificationQuota = globalNotificationQuota;
         this.dataBroker = Preconditions.checkNotNull(dataBroker);
-        hashedWheelTimer = new HashedWheelTimer(TICK_DURATION, TimeUnit.MILLISECONDS, 500);
         /* merge empty nodes to oper DS to predict any problems with missing parent for Node */
         final WriteTransaction tx = dataBroker.newWriteOnlyTransaction();
 
@@ -103,9 +101,11 @@ public class DeviceManagerImpl implements DeviceManager, ExtensionConverterProvi
             throw new IllegalStateException(e);
         }
 
-        this.messageIntelligenceAgency = messageIntelligenceAgency;
         this.barrierIntervalNanos = TimeUnit.MILLISECONDS.toNanos(barrierInterval);
         this.barrierCountLimit = barrierCountLimit;
+
+        this.conductor = lifecycleConductor;
+        spyPool = new ScheduledThreadPoolExecutor(1);
     }
 
 
@@ -115,23 +115,31 @@ public class DeviceManagerImpl implements DeviceManager, ExtensionConverterProvi
     }
 
     @Override
-    public void onDeviceContextLevelUp(final DeviceContext deviceContext) throws Exception {
+    public void onDeviceContextLevelUp(final NodeId nodeId) throws Exception {
         // final phase - we have to add new Device to MD-SAL DataStore
-        LOG.debug("Final phase of DeviceContextLevelUp for Node: {} ", deviceContext.getDeviceState().getNodeId());
-        Preconditions.checkNotNull(deviceContext);
+        LOG.debug("Final phase of DeviceContextLevelUp for Node: {} ", nodeId);
+        DeviceContext deviceContext = Preconditions.checkNotNull(deviceContexts.get(nodeId));
         ((DeviceContextImpl) deviceContext).initialSubmitTransaction();
         deviceContext.onPublished();
     }
 
     @Override
-    public void deviceConnected(@CheckForNull final ConnectionContext connectionContext) throws Exception {
+    public boolean deviceConnected(@CheckForNull final ConnectionContext connectionContext) throws Exception {
         Preconditions.checkArgument(connectionContext != null);
-        Preconditions.checkState(!deviceContexts.containsKey(connectionContext.getNodeId()),
-                "Rejecting connection from node which is already connected and there exist deviceContext for it: {}",
-                connectionContext.getNodeId()
-        );
+
+        NodeId nodeId = connectionContext.getNodeId();
+        /**
+         * This part prevent destroy another device context. Throwing here an exception result to propagate close connection
+         * in {@link org.opendaylight.openflowplugin.impl.connection.org.opendaylight.openflowplugin.impl.connection.HandshakeContextImpl}
+         * If context already exist we are in state closing process (connection flapping) and we should not propagate connection close
+         */
+         if (deviceContexts.containsKey(nodeId)) {
+            LOG.warn("Rejecting connection from node which is already connected and there exist deviceContext for it: {}", connectionContext.getNodeId());
+             return false;
+         }
+
         LOG.info("ConnectionEvent: Device connected to controller, Device:{}, NodeId:{}",
-                connectionContext.getConnectionAdapter().getRemoteAddress(), connectionContext.getNodeId());
+                connectionContext.getConnectionAdapter().getRemoteAddress(), nodeId);
 
         // Add Disconnect handler
         connectionContext.setDeviceDisconnectedHandler(DeviceManagerImpl.this);
@@ -150,14 +158,18 @@ public class DeviceManagerImpl implements DeviceManager, ExtensionConverterProvi
         connectionContext.setOutboundQueueHandleRegistration(outboundQueueHandlerRegistration);
 
         final DeviceState deviceState = createDeviceState(connectionContext);
-        final DeviceContext deviceContext = new DeviceContextImpl(connectionContext, deviceState, dataBroker,
-                hashedWheelTimer, messageIntelligenceAgency, outboundQueueProvider, translatorLibrary, switchFeaturesMandatory);
+        final DeviceContext deviceContext = new DeviceContextImpl(connectionContext,
+                deviceState,
+                dataBroker,
+                conductor.getMessageIntelligenceAgency(),
+                outboundQueueProvider,
+                translatorLibrary,
+                switchFeaturesMandatory);
 
-        Verify.verify(deviceContexts.putIfAbsent(connectionContext.getNodeId(), deviceContext) == null, "DeviceCtx still not closed.");
-        deviceContext.addDeviceContextClosedHandler(this);
+        Verify.verify(deviceContexts.putIfAbsent(nodeId, deviceContext) == null, "DeviceCtx still not closed.");
 
         ((ExtensionConverterProviderKeeper) deviceContext).setExtensionConverterProvider(extensionConverterProvider);
-        deviceContext.setNotificationService(notificationService);
+        deviceContext.setStatisticsRpcEnabled(isStatisticsRpcEnabled);
         deviceContext.setNotificationPublishService(notificationPublishService);
 
         updatePacketInRateLimiters();
@@ -167,7 +179,9 @@ public class DeviceManagerImpl implements DeviceManager, ExtensionConverterProvi
         connectionAdapter.setMessageListener(messageListener);
         deviceState.setValid(true);
 
-        deviceInitPhaseHandler.onDeviceContextLevelUp(deviceContext);
+        deviceInitPhaseHandler.onDeviceContextLevelUp(nodeId);
+
+        return true;
     }
 
     private static DeviceStateImpl createDeviceState(final @Nonnull ConnectionContext connectionContext) {
@@ -200,11 +214,6 @@ public class DeviceManagerImpl implements DeviceManager, ExtensionConverterProvi
         this.translatorLibrary = translatorLibrary;
     }
 
-    @Override
-    public void setNotificationService(final NotificationService notificationServiceParam) {
-        notificationService = notificationServiceParam;
-    }
-
     @Override
     public void setNotificationPublishService(final NotificationPublishService notificationService) {
         notificationPublishService = notificationService;
@@ -234,8 +243,17 @@ public class DeviceManagerImpl implements DeviceManager, ExtensionConverterProvi
 
     @Override
     public void initialize() {
-        spyPool = new ScheduledThreadPoolExecutor(1);
-        spyPool.scheduleAtFixedRate(messageIntelligenceAgency, spyRate, spyRate, TimeUnit.SECONDS);
+        spyPool.scheduleAtFixedRate(conductor.getMessageIntelligenceAgency(), spyRate, spyRate, TimeUnit.SECONDS);
+    }
+
+    @Override
+    public DeviceContext getDeviceContextFromNodeId(final NodeId nodeId) {
+        return deviceContexts.get(nodeId);
+    }
+
+    @Override
+    public void setStatisticsRpcEnabled(boolean isStatisticsRpcEnabled) {
+        this.isStatisticsRpcEnabled = isStatisticsRpcEnabled;
     }
 
     @Override
@@ -256,13 +274,11 @@ public class DeviceManagerImpl implements DeviceManager, ExtensionConverterProvi
     @Override
     public void onDeviceDisconnected(final ConnectionContext connectionContext) {
         LOG.trace("onDeviceDisconnected method call for Node: {}", connectionContext.getNodeId());
-        Preconditions.checkArgument(connectionContext != null);
         final NodeId nodeId = connectionContext.getNodeId();
         final DeviceContext deviceCtx = this.deviceContexts.get(nodeId);
 
         if (null == deviceCtx) {
-            LOG.info("DeviceContext for Node {} was not found. Connection is terminated without OFP context suite.",
-                    connectionContext.getNodeId());
+            LOG.info("DeviceContext for Node {} was not found. Connection is terminated without OFP context suite.", nodeId);
             return;
         }
 
@@ -276,13 +292,13 @@ public class DeviceManagerImpl implements DeviceManager, ExtensionConverterProvi
 
                 @Override
                 public void onSuccess(final Void result) {
-                    LOG.debug("TxChainManager for device {} is closed successful.", deviceCtx.getDeviceState().getNodeId());
+                    LOG.debug("TxChainManager for device {} is closed successful.", nodeId);
                     deviceTerminPhaseHandler.onDeviceContextLevelDown(deviceCtx);
                 }
 
                 @Override
                 public void onFailure(final Throwable t) {
-                    LOG.warn("TxChainManager for device {} failed by closing.", deviceCtx.getDeviceState().getNodeId(), t);
+                    LOG.warn("TxChainManager for device {} failed by closing.", nodeId, t);
                     deviceTerminPhaseHandler.onDeviceContextLevelDown(deviceCtx);
                 }
             });
@@ -292,13 +308,17 @@ public class DeviceManagerImpl implements DeviceManager, ExtensionConverterProvi
                 @Override
                 public void run(final Timeout timeout) throws Exception {
                     if (!future.isDone()) {
-                        LOG.info("Shutting down TxChain for node {} not completed during 10 sec. Continue anyway.",
-                                deviceCtx.getDeviceState().getNodeId());
+                        LOG.info("Shutting down TxChain for node {} not completed during 10 sec. Continue anyway.", nodeId);
                         future.cancel(false);
                     }
                 }
             };
-            deviceCtx.getTimer().newTimeout(timerTask, 10, TimeUnit.SECONDS);
+            conductor.newTimeout(timerTask, 10, TimeUnit.SECONDS);
         }
     }
+
+    @VisibleForTesting
+    void addDeviceContextToMap(final NodeId nodeId, final DeviceContext deviceContext){
+        deviceContexts.put(nodeId, deviceContext);
+    }
 }
index b14eba4700e0527acc6582b4dcad7e3972578d2f..4276bfe54bcf484267d3ed05a24da5b9c7b2b8a3 100644 (file)
@@ -189,22 +189,26 @@ class TransactionChainManager implements TransactionChainListener, AutoCloseable
     }
 
     <T extends DataObject> void addDeleteOperationTotTxChain(final LogicalDatastoreType store,
-                                                             final InstanceIdentifier<T> path) {
+                                                             final InstanceIdentifier<T> path) throws Exception {
         final WriteTransaction writeTx = getTransactionSafely();
         if (writeTx != null) {
+            LOG.trace("addDeleteOperation called with path {} ", path);
             writeTx.delete(store, path);
         } else {
             LOG.debug("WriteTx is null for node {}. Delete {} was not realized.", nodeII, path);
+            throw new Exception("Cannot write into transaction.");
         }
     }
 
     <T extends DataObject> void writeToTransaction(final LogicalDatastoreType store,
-                                                   final InstanceIdentifier<T> path, final T data) {
+                                                   final InstanceIdentifier<T> path, final T data) throws Exception {
         final WriteTransaction writeTx = getTransactionSafely();
         if (writeTx != null) {
+            LOG.trace("writeToTransaction called with path {} ", path);
             writeTx.put(store, path, data);
         } else {
             LOG.debug("WriteTx is null for node {}. Write data for {} was not realized.", nodeII, path);
+            throw new Exception("Cannot write into transaction.");
         }
     }
 
@@ -252,7 +256,7 @@ class TransactionChainManager implements TransactionChainListener, AutoCloseable
     }
 
     ListenableFuture<Void> shuttingDown() {
-        LOG.debug("TxManager is going SUTTING_DOWN for node {}", nodeII);
+        LOG.debug("TxManager is going SHUTTING_DOWN for node {}", nodeII);
         ListenableFuture<Void> future;
         synchronized (txLock) {
             this.transactionChainManagerStatus = TransactionChainManagerStatus.SHUTTING_DOWN;
index 8546fe7dd1d1fb1c0aa58372695e6a89eff91055..8cd41133159384c3f360f5538b085a2086590388 100644 (file)
  */
 package org.opendaylight.openflowplugin.impl.role;
 
-import javax.annotation.Nullable;
-import java.util.concurrent.Future;
-
-import com.google.common.annotations.VisibleForTesting;
 import com.google.common.base.Preconditions;
-import com.google.common.base.Verify;
-import com.google.common.util.concurrent.AsyncFunction;
-import com.google.common.util.concurrent.FutureCallback;
-import com.google.common.util.concurrent.Futures;
-import com.google.common.util.concurrent.JdkFutureAdapters;
-import com.google.common.util.concurrent.ListenableFuture;
-import io.netty.util.Timeout;
-import io.netty.util.TimerTask;
-import java.util.concurrent.Future;
+
 import java.util.concurrent.Semaphore;
 import java.util.concurrent.TimeUnit;
+import javax.annotation.Nonnull;
 import javax.annotation.Nullable;
-import javax.annotation.concurrent.GuardedBy;
+
+import org.opendaylight.controller.md.sal.common.api.clustering.CandidateAlreadyRegisteredException;
 import org.opendaylight.controller.md.sal.common.api.clustering.Entity;
 import org.opendaylight.controller.md.sal.common.api.clustering.EntityOwnershipCandidateRegistration;
 import org.opendaylight.controller.md.sal.common.api.clustering.EntityOwnershipService;
-import org.opendaylight.openflowplugin.api.OFConstants;
-import org.opendaylight.openflowplugin.api.openflow.connection.ConnectionContext;
-import org.opendaylight.openflowplugin.api.openflow.device.DeviceContext;
-import org.opendaylight.openflowplugin.api.openflow.device.DeviceState;
 import org.opendaylight.openflowplugin.api.openflow.device.RequestContext;
+import org.opendaylight.openflowplugin.api.openflow.lifecycle.LifecycleConductor;
 import org.opendaylight.openflowplugin.api.openflow.role.RoleContext;
+import org.opendaylight.openflowplugin.impl.LifecycleConductorImpl;
 import org.opendaylight.openflowplugin.impl.rpc.AbstractRequestContext;
-import org.opendaylight.openflowplugin.impl.services.SalRoleServiceImpl;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRef;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.role.service.rev150727.OfpRole;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.role.service.rev150727.SalRoleService;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.role.service.rev150727.SetRoleInput;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.role.service.rev150727.SetRoleInputBuilder;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.role.service.rev150727.SetRoleOutput;
-import org.opendaylight.yangtools.yang.common.RpcResult;
-import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 /**
- * Created by kramesha on 9/12/15.
+ * Role context hold information about entity ownership registration,
+ * register and unregister candidate (main and tx)
  */
-public class RoleContextImpl implements RoleContext {
+class RoleContextImpl implements RoleContext {
+
     private static final Logger LOG = LoggerFactory.getLogger(RoleContextImpl.class);
+    private static final int TIMEOUT = 12;
 
+    private final NodeId nodeId;
     private final EntityOwnershipService entityOwnershipService;
-    private EntityOwnershipCandidateRegistration entityOwnershipCandidateRegistration;
-    private EntityOwnershipCandidateRegistration txEntityOwnershipCandidateRegistration;
-
-    private final DeviceContext deviceContext;
+    private volatile EntityOwnershipCandidateRegistration entityOwnershipCandidateRegistration = null;
+    private volatile EntityOwnershipCandidateRegistration txEntityOwnershipCandidateRegistration = null;
 
-    @GuardedBy("mainCandidateGuard")
     private final Entity entity;
-    @GuardedBy("txCandidateGuard")
     private final Entity txEntity;
 
-    private SalRoleService salRoleService;
+    private SalRoleService salRoleService = null;
 
     private final Semaphore roleChangeGuard = new Semaphore(1, true);
 
-    @GuardedBy("roleChangeGuard")
-    private OfpRole clusterRole;
+    private final LifecycleConductor conductor;
 
-    public RoleContextImpl(final DeviceContext deviceContext, final EntityOwnershipService entityOwnershipService,
-                           final Entity entity, final Entity txEntity) {
-        this.entityOwnershipService = Preconditions.checkNotNull(entityOwnershipService);
-        this.deviceContext = Preconditions.checkNotNull(deviceContext);
-        this.entity = Preconditions.checkNotNull(entity);
-        this.txEntity = Preconditions.checkNotNull(txEntity);
-        salRoleService = new SalRoleServiceImpl(this, deviceContext);
-        clusterRole = OfpRole.BECOMESLAVE;
+    public RoleContextImpl(final NodeId nodeId, final EntityOwnershipService entityOwnershipService, final Entity entity, final Entity txEntity, final LifecycleConductor lifecycleConductor) {
+        this.entityOwnershipService = entityOwnershipService;
+        this.entity = entity;
+        this.txEntity = txEntity;
+        this.nodeId = nodeId;
+        this.conductor = lifecycleConductor;
     }
 
     @Override
-    public void initializationRoleContext() {
-        LOG.trace("Initialization MainCandidate for Node {}", deviceContext.getDeviceState().getNodeId());
-        final AsyncFunction<RpcResult<SetRoleOutput>, Void> initFunction = new AsyncFunction<RpcResult<SetRoleOutput>, Void>() {
-            @Override
-            public ListenableFuture<Void> apply(final RpcResult<SetRoleOutput> input) throws Exception {
-                LOG.debug("Initialization request OpenflowEntityOwnership for entity {}", entity);
-                getDeviceState().setRole(OfpRole.BECOMESLAVE);
-                entityOwnershipCandidateRegistration = entityOwnershipService.registerCandidate(entity);
-                LOG.debug("RoleContextImpl : Candidate registered with ownership service for device :{}", deviceContext
-                        .getPrimaryConnectionContext().getNodeId().getValue());
-                return Futures.immediateFuture(null);
-            }
-        };
-
-        try {
-            roleChangeGuard.acquire();
-            final ListenableFuture<Void> roleChange = sendRoleChangeToDevice(OfpRole.BECOMESLAVE, initFunction);
-            Futures.addCallback(roleChange, new FutureCallback<Void>() {
-
-                @Override
-                public void onSuccess(final Void result) {
-                    LOG.debug("Initial RoleContext for Node {} is successful", deviceContext.getDeviceState().getNodeId());
-                    roleChangeGuard.release();
-                }
-
-                @Override
-                public void onFailure(final Throwable t) {
-                    LOG.warn("Initial RoleContext for Node {} fail", deviceContext.getDeviceState().getNodeId(), t);
-                    roleChangeGuard.release();
-                    deviceContext.shutdownConnection();
-                }
-            });
-        } catch (final Exception e) {
-            LOG.warn("Unexpected exception bu Initialization RoleContext for Node {}", deviceContext.getDeviceState().getNodeId(), e);
-            roleChangeGuard.release();
-            deviceContext.shutdownConnection();
-        }
-    }
-
-    @Override
-    public void terminationRoleContext() {
-        LOG.trace("Termination MainCandidate for Node {}", deviceContext.getDeviceState().getNodeId());
-        if (null != entityOwnershipCandidateRegistration) {
-            LOG.debug("Closing EntityOwnershipCandidateRegistration for {}", entity);
-            try {
-                roleChangeGuard.acquire();
-            } catch (final InterruptedException e) {
-                LOG.warn("Unexpected exception in closing EntityOwnershipCandidateRegistration process for entity {}", entity);
-            } finally {
-                entityOwnershipCandidateRegistration.close();
-                entityOwnershipCandidateRegistration = null;
-                // FIXME: call suspendTxCandidate here means lost protection for possible Delete Node before take ownership
-                // by another ClusterNode, but it stabilized cluster behavior in general - So try to find another solution
-                suspendTxCandidate();
-                roleChangeGuard.release();
-            }
-        }
-    }
-
-    @Override
-    public void onDeviceTryToTakeClusterLeadership() {
-        LOG.trace("onDeviceTryToTakeClusterLeadership method call for Entity {}", entity);
-        boolean callShutdown = false;
-        try {
-            roleChangeGuard.acquire();
-            Verify.verify(null != entityOwnershipCandidateRegistration);
-            Verify.verify(OfpRole.BECOMESLAVE.equals(clusterRole));
-
-            clusterRole = OfpRole.BECOMEMASTER;
-            /* register TxCandidate and wait for mainCandidateGuard release from onDeviceTakeLeadership method */
-            setupTxCandidate();
-
-        } catch (final Exception e) {
-            LOG.warn("Unexpected exception in roleChange process for entity {}", entity);
-            callShutdown = true;
-        } finally {
-            roleChangeGuard.release();
-        }
-        if (callShutdown) {
-            deviceContext.shutdownConnection();
-        }
+    public boolean initialization() {
+        LOG.info("Initialization main candidate for node {}", nodeId);
+        return registerCandidate(this.entity);
     }
 
     @Override
-    public void onDeviceTakeClusterLeadership() {
-        LOG.trace("onDeviceTakeClusterLeadership for entity {}", txEntity);
-        try {
-            roleChangeGuard.acquire();
-            Verify.verify(null != txEntityOwnershipCandidateRegistration);
-            Verify.verify(OfpRole.BECOMEMASTER.equals(clusterRole));
-
-            if (null == entityOwnershipCandidateRegistration) {
-                LOG.debug("EntityOwnership candidate for entity {} is closed.", txEntity);
-                suspendTxCandidate();
-                roleChangeGuard.release();
-                return;
-            }
-
-            final ListenableFuture<Void> future = onRoleChanged(OfpRole.BECOMESLAVE, OfpRole.BECOMEMASTER);
-            Futures.addCallback(future, new FutureCallback<Void>() {
-
-                @Override
-                public void onSuccess(final Void result) {
-                    LOG.debug("Take Leadership for node {} was successful", getDeviceState().getNodeId());
-                    roleChangeGuard.release();
-                }
-
-                @Override
-                public void onFailure(final Throwable t) {
-                    LOG.warn("Take Leadership for node {} failed", getDeviceState().getNodeId(), t);
-                    roleChangeGuard.release();
-                    deviceContext.shutdownConnection();
-                }
-            });
-
-        } catch (final Exception e) {
-            LOG.warn("Unexpected exception in roleChange process for entity {}", txEntity);
-            roleChangeGuard.release();
-            deviceContext.shutdownConnection();
+    public void unregisterAllCandidates() {
+        LOG.info("Role context closed, unregistering all candidates for ownership for node {}", nodeId);
+        if (isMainCandidateRegistered()) {
+            unregisterCandidate(this.entity);
         }
-    };
-
-    @Override
-    public void onDeviceLostClusterLeadership() {
-        LOG.trace("onDeviceLostClusterLeadership method call for Entity {}", entity);
-        try {
-            roleChangeGuard.acquire();
-            Verify.verify(null != entityOwnershipCandidateRegistration);
-            Verify.verify(null != txEntityOwnershipCandidateRegistration);
-            Verify.verify(OfpRole.BECOMEMASTER.equals(clusterRole));
-
-            clusterRole = OfpRole.BECOMESLAVE;
-
-            final ListenableFuture<Void> future = onRoleChanged(OfpRole.BECOMEMASTER, OfpRole.BECOMESLAVE);
-            Futures.addCallback(future, new FutureCallback<Void>() {
-
-                @Override
-                public void onSuccess(final Void result) {
-                    LOG.debug("Lost Leadership for node {} was successful", getDeviceState().getNodeId());
-                    suspendTxCandidate();
-                    roleChangeGuard.release();
-                }
-
-                @Override
-                public void onFailure(final Throwable t) {
-                    LOG.debug("Lost Leadership for node {} faild", getDeviceState().getNodeId(), t);
-                    roleChangeGuard.release();
-                    deviceContext.shutdownConnection();
-                }
-
-            });
-
-        } catch (final Exception e) {
-            LOG.warn("Unexpected exception in roleChange process for entity {}", entity);
-            roleChangeGuard.release();
-            deviceContext.shutdownConnection();
+        if (isTxCandidateRegistered()) {
+            unregisterCandidate(this.txEntity);
         }
     }
 
+    @Nullable
     @Override
-    public boolean isMainCandidateRegistered() {
-        final boolean result;
-        try {
-            roleChangeGuard.acquire();
-        } catch (final InterruptedException e) {
-            LOG.warn("Unexpected exception in check EntityOwnershipCandidateRegistration process for entity {}", entity);
-        } finally {
-            result = entityOwnershipCandidateRegistration != null;
-            roleChangeGuard.release();
-        }
-        return result;
-    }
-
-    @Override
-    public boolean isTxCandidateRegistered() {
-        final boolean result;
-        try {
-            roleChangeGuard.acquire();
-        } catch (final InterruptedException e) {
-            LOG.warn("Unexpected exception in check TxEntityOwnershipCandidateRegistration process for txEntity {}", txEntity);
-        } finally {
-            result = txEntityOwnershipCandidateRegistration != null;
-            roleChangeGuard.release();
-        }
-        return result;
-    }
-
-    @VisibleForTesting
-    ListenableFuture<Void> onRoleChanged(final OfpRole oldRole, final OfpRole newRole) {
-        LOG.trace("onRoleChanged method call for Entity {}", entity);
-
-        if (!isDeviceConnected()) {
-            // this can happen as after the disconnect, we still get a last message from EntityOwnershipService.
-            LOG.debug("Device {} is disconnected from this node. Hence not attempting a role change.", deviceContext
-                    .getPrimaryConnectionContext().getNodeId());
-            // we don't need to do anything
-            return Futures.immediateFuture(null);
-        }
-
-        final AsyncFunction<RpcResult<SetRoleOutput>, Void> roleChangeFunction = new AsyncFunction<RpcResult<SetRoleOutput>, Void>() {
+    public <T> RequestContext<T> createRequestContext() {
+        return new AbstractRequestContext<T>(conductor.reserveXidForDeviceMessage(nodeId)) {
             @Override
-            public ListenableFuture<Void> apply(final RpcResult<SetRoleOutput> setRoleOutputRpcResult) throws Exception {
-                LOG.debug("Role change {} successful made on switch :{}", newRole, deviceContext.getDeviceState().getNodeId());
-                getDeviceState().setRole(newRole);
-                return deviceContext.onClusterRoleChange(oldRole, newRole);
+            public void close() {
             }
         };
-        return sendRoleChangeToDevice(newRole, roleChangeFunction);
     }
 
-    @GuardedBy("roleChangeGuard")
-    private void setupTxCandidate() throws Exception {
-        LOG.debug("setupTxCandidate for entity {} and Transaction entity {}", entity, txEntity);
-        Verify.verify(txEntity != null);
-        Verify.verify(entityOwnershipCandidateRegistration != null);
-        Verify.verify(txEntityOwnershipCandidateRegistration == null);
-        txEntityOwnershipCandidateRegistration = entityOwnershipService.registerCandidate(txEntity);
-    }
-
-    @GuardedBy("roleChangeGuard")
-    private void suspendTxCandidate() {
-        LOG.trace("Suspend TxCandidate for Node {}", deviceContext.getDeviceState().getNodeId());
-        if (null != txEntityOwnershipCandidateRegistration) {
-            LOG.debug("Closing TxEntityOwnershipCandidateRegistration for {}", txEntity);
-            txEntityOwnershipCandidateRegistration.close();
-            txEntityOwnershipCandidateRegistration = null;
-        }
+    @Override
+    public void setSalRoleService(@Nonnull final SalRoleService salRoleService) {
+        Preconditions.checkNotNull(salRoleService);
+        this.salRoleService = salRoleService;
     }
 
     @Override
-    public void close() {
-        LOG.trace("Close RoleCtx for Node {}", deviceContext.getDeviceState().getNodeId());
-        if (null != entityOwnershipCandidateRegistration) {
-            LOG.info("Close Node Entity {} registration", entity);
-            entityOwnershipCandidateRegistration.close();
-            entityOwnershipCandidateRegistration = null;
-        }
-        if (null != txEntityOwnershipCandidateRegistration) {
-            LOG.info("Close Tx Entity {} registration", txEntity);
-            txEntityOwnershipCandidateRegistration.close();
-            txEntityOwnershipCandidateRegistration = null;
-        }
+    public SalRoleService getSalRoleService() {
+        return this.salRoleService;
     }
 
     @Override
     public Entity getEntity() {
-        return entity;
+        return this.entity;
     }
 
     @Override
     public Entity getTxEntity() {
-        return txEntity;
-    }
-
-    private boolean isDeviceConnected() {
-        return ConnectionContext.CONNECTION_STATE.WORKING.equals(
-                deviceContext.getPrimaryConnectionContext().getConnectionState());
+        return this.txEntity;
     }
 
-    @Nullable
     @Override
-    public <T> RequestContext<T> createRequestContext() {
-        final AbstractRequestContext<T> ret = new AbstractRequestContext<T>(deviceContext.reservedXidForDeviceMessage()) {
-            @Override
-            public void close() {
-            }
-        };
-        return ret;
-    }
-
-    @VisibleForTesting
-    void setSalRoleService(final SalRoleService salRoleService) {
-        this.salRoleService = salRoleService;
+    public NodeId getNodeId() {
+        return nodeId;
     }
 
     @Override
-    public DeviceState getDeviceState() {
-        return deviceContext.getDeviceState();
+    public boolean isMainCandidateRegistered() {
+        return entityOwnershipCandidateRegistration != null;
     }
 
     @Override
-    public DeviceContext getDeviceContext() {
-        return deviceContext;
+    public boolean isTxCandidateRegistered() {
+        return txEntityOwnershipCandidateRegistration != null;
     }
 
-    private ListenableFuture<Void> sendRoleChangeToDevice(final OfpRole newRole, final AsyncFunction<RpcResult<SetRoleOutput>, Void> function) {
-        LOG.debug("Send new role {} to device {}", newRole, deviceContext.getDeviceState().getNodeId());
-        final Future<RpcResult<SetRoleOutput>> setRoleOutputFuture;
-        if (deviceContext.getDeviceState().getFeatures().getVersion() < OFConstants.OFP_VERSION_1_3) {
-            LOG.debug("Device OF version {} not support ROLE", deviceContext.getDeviceState().getFeatures().getVersion());
-            setRoleOutputFuture = Futures.immediateFuture(RpcResultBuilder.<SetRoleOutput> success().build());
-        } else {
-            final SetRoleInput setRoleInput = (new SetRoleInputBuilder()).setControllerRole(newRole)
-                    .setNode(new NodeRef(deviceContext.getDeviceState().getNodeInstanceIdentifier())).build();
-            setRoleOutputFuture = salRoleService.setRole(setRoleInput);
-            final TimerTask timerTask = new TimerTask() {
-
-                @Override
-                public void run(final Timeout timeout) throws Exception {
-                    if (!setRoleOutputFuture.isDone()) {
-                        LOG.info("New role {} was not propagated to device {} during 10 sec. Close connection immediately.",
-                                newRole, deviceContext.getDeviceState().getNodeId());
-                        setRoleOutputFuture.cancel(true);
-                    }
+    @Override
+    public boolean registerCandidate(final Entity entity_) {
+        boolean permit = false;
+        try {
+            permit = roleChangeGuard.tryAcquire(TIMEOUT, TimeUnit.SECONDS);
+            if(permit) {
+                LOG.debug("Register candidate for entity {}", entity_);
+                if (entity_.equals(this.entity)) {
+                    entityOwnershipCandidateRegistration = entityOwnershipService.registerCandidate(entity_);
+                } else {
+                    txEntityOwnershipCandidateRegistration = entityOwnershipService.registerCandidate(entity_);
                 }
-            };
-            deviceContext.getTimer().newTimeout(timerTask, 10, TimeUnit.SECONDS);
+            } else {
+                return false;
+            }
+        } catch (final CandidateAlreadyRegisteredException e) {
+            LOG.warn("Candidate for entity {} is already registered.", entity_.getType());
+            return false;
+        } catch (final InterruptedException e) {
+            LOG.warn("Cannot acquire semaphore for register entity {} candidate.", entity_.getType());
+            return false;
+        } finally {
+            if (permit) {
+                roleChangeGuard.release();
+            }
         }
-        return Futures.transform(JdkFutureAdapters.listenInPoolThread(setRoleOutputFuture), function);
+        return true;
     }
 
-
     @Override
-    public OfpRole getClusterRole() {
-        final OfpRole role;
+    public boolean unregisterCandidate(final Entity entity_) {
+        boolean permit = false;
         try {
-            roleChangeGuard.acquire();
+            permit = roleChangeGuard.tryAcquire(TIMEOUT, TimeUnit.SECONDS);
+            if(permit) {
+                if (entity_.equals(this.entity)) {
+                    if (entityOwnershipCandidateRegistration != null) {
+                        LOG.debug("Unregister candidate for entity {}", entity_);
+                        entityOwnershipCandidateRegistration.close();
+                        entityOwnershipCandidateRegistration = null;
+                    }
+                } else {
+                    if (txEntityOwnershipCandidateRegistration != null) {
+                        LOG.debug("Unregister candidate for tx entity {}", entity_);
+                        txEntityOwnershipCandidateRegistration.close();
+                        txEntityOwnershipCandidateRegistration = null;
+                    }
+                }
+            } else {
+                return false;
+            }
         } catch (final InterruptedException e) {
-            LOG.warn("Unexpected exception in get ClusterRole process for entity {}", entity);
+            LOG.warn("Cannot acquire semaphore for unregister entity {} candidate.", entity_.getType());
+            return false;
         } finally {
-            role = OfpRole.forValue(clusterRole.getIntValue());
-            roleChangeGuard.release();
+            if (permit) {
+                roleChangeGuard.release();
+            }
         }
-        return role;
+        return true;
     }
 
+    @Override
+    public void close() {
+        unregisterAllCandidates();
+    }
+
+    public boolean isMaster(){
+        return (txEntityOwnershipCandidateRegistration != null && entityOwnershipCandidateRegistration != null);
+    }
 }
index 2e947b8eba33256d925408a2e22e25cce9045c2b..9e8d940babe3245f63ae61414196a70b45148e13 100644 (file)
@@ -7,20 +7,29 @@
  */
 package org.opendaylight.openflowplugin.impl.role;
 
+import com.google.common.annotations.VisibleForTesting;
 import com.google.common.base.Preconditions;
 import com.google.common.base.Verify;
 import com.google.common.collect.Iterators;
 import com.google.common.util.concurrent.CheckedFuture;
 import com.google.common.util.concurrent.FutureCallback;
 import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.JdkFutureAdapters;
+import com.google.common.util.concurrent.ListenableFuture;
 import io.netty.util.Timeout;
 import io.netty.util.TimerTask;
+
+import java.util.ArrayList;
 import java.util.Iterator;
+import java.util.List;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.ConcurrentMap;
+import java.util.concurrent.Future;
 import java.util.concurrent.TimeUnit;
 import javax.annotation.CheckForNull;
 import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
 import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
 import org.opendaylight.controller.md.sal.common.api.clustering.Entity;
@@ -30,41 +39,54 @@ import org.opendaylight.controller.md.sal.common.api.clustering.EntityOwnershipL
 import org.opendaylight.controller.md.sal.common.api.clustering.EntityOwnershipService;
 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
 import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
+import org.opendaylight.openflowplugin.api.OFConstants;
 import org.opendaylight.openflowplugin.api.openflow.device.DeviceContext;
-import org.opendaylight.openflowplugin.api.openflow.device.DeviceState;
 import org.opendaylight.openflowplugin.api.openflow.device.handlers.DeviceInitializationPhaseHandler;
 import org.opendaylight.openflowplugin.api.openflow.device.handlers.DeviceTerminationPhaseHandler;
-import org.opendaylight.openflowplugin.api.openflow.role.RoleChangeListener;
+import org.opendaylight.openflowplugin.api.openflow.lifecycle.LifecycleConductor;
+import org.opendaylight.openflowplugin.api.openflow.lifecycle.RoleChangeListener;
+import org.opendaylight.openflowplugin.api.openflow.lifecycle.ServiceChangeListener;
 import org.opendaylight.openflowplugin.api.openflow.role.RoleContext;
 import org.opendaylight.openflowplugin.api.openflow.role.RoleManager;
+import org.opendaylight.openflowplugin.impl.services.SalRoleServiceImpl;
+import org.opendaylight.openflowplugin.impl.util.DeviceStateUtil;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRef;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.role.service.rev150727.OfpRole;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.role.service.rev150727.SetRoleInput;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.role.service.rev150727.SetRoleInputBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.role.service.rev150727.SetRoleOutput;
+import org.opendaylight.yangtools.yang.common.RpcResult;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 /**
  * Gets invoked from RpcManagerInitial, registers a candidate with EntityOwnershipService.
- * On receipt of the ownership notification, makes an rpc call to SalRoleSevice.
+ * On receipt of the ownership notification, makes an rpc call to SalRoleService.
  *
  * Hands over to StatisticsManager at the end.
  */
-public class RoleManagerImpl implements RoleManager, EntityOwnershipListener {
+public class RoleManagerImpl implements RoleManager, EntityOwnershipListener, ServiceChangeListener {
     private static final Logger LOG = LoggerFactory.getLogger(RoleManagerImpl.class);
 
     private DeviceInitializationPhaseHandler deviceInitializationPhaseHandler;
     private DeviceTerminationPhaseHandler deviceTerminationPhaseHandler;
     private final DataBroker dataBroker;
     private final EntityOwnershipService entityOwnershipService;
-    private final ConcurrentMap<Entity, RoleContext> contexts = new ConcurrentHashMap<>();
-    private final ConcurrentMap<Entity, RoleContext> txContexts = new ConcurrentHashMap<>();
+    private final ConcurrentMap<NodeId, RoleContext> contexts = new ConcurrentHashMap<>();
+    private final ConcurrentMap<Entity, RoleContext> watchingEntities = new ConcurrentHashMap<>();
     private final EntityOwnershipListenerRegistration entityOwnershipListenerRegistration;
     private final EntityOwnershipListenerRegistration txEntityOwnershipListenerRegistration;
+    private List<RoleChangeListener> listeners = new ArrayList<>();
+
+    private final LifecycleConductor conductor;
 
-    public RoleManagerImpl(final EntityOwnershipService entityOwnershipService, final DataBroker dataBroker) {
+    public RoleManagerImpl(final EntityOwnershipService entityOwnershipService, final DataBroker dataBroker, final LifecycleConductor lifecycleConductor) {
         this.entityOwnershipService = Preconditions.checkNotNull(entityOwnershipService);
         this.dataBroker = Preconditions.checkNotNull(dataBroker);
         this.entityOwnershipListenerRegistration = Preconditions.checkNotNull(entityOwnershipService.registerListener(RoleManager.ENTITY_TYPE, this));
         this.txEntityOwnershipListenerRegistration = Preconditions.checkNotNull(entityOwnershipService.registerListener(TX_ENTITY_TYPE, this));
+        this.conductor = lifecycleConductor;
         LOG.debug("Register OpenflowOwnershipListener to all entity ownership changes");
     }
 
@@ -74,211 +96,297 @@ public class RoleManagerImpl implements RoleManager, EntityOwnershipListener {
     }
 
     @Override
-    public void onDeviceContextLevelUp(@CheckForNull final DeviceContext deviceContext) throws Exception {
-        LOG.trace("Role manager called for device:{}", deviceContext.getPrimaryConnectionContext().getNodeId());
-        final RoleContext roleContext = new RoleContextImpl(deviceContext, entityOwnershipService,
-                makeEntity(deviceContext.getDeviceState().getNodeId()),
-                makeTxEntity(deviceContext.getDeviceState().getNodeId()));
-
-        Verify.verify(contexts.putIfAbsent(roleContext.getEntity(), roleContext) == null, "Role context for master Node {} is still not closed.", deviceContext.getDeviceState().getNodeId());
-        Verify.verify(!txContexts.containsKey(roleContext.getTxEntity()),
-                "Role context for master Node {} is still not closed. TxEntity was not unregistered yet.", deviceContext.getDeviceState().getNodeId());
-
-        // if the device context gets closed (mostly on connection close), we would need to cleanup
-        deviceContext.addDeviceContextClosedHandler(this);
-        roleContext.initializationRoleContext();
-        deviceInitializationPhaseHandler.onDeviceContextLevelUp(deviceContext);
+    public void onDeviceContextLevelUp(@CheckForNull final NodeId nodeId) throws Exception {
+        final DeviceContext deviceContext = Preconditions.checkNotNull(conductor.getDeviceContext(nodeId));
+        final RoleContext roleContext = new RoleContextImpl(nodeId, entityOwnershipService, makeEntity(nodeId), makeTxEntity(nodeId), conductor);
+        roleContext.setSalRoleService(new SalRoleServiceImpl(roleContext, deviceContext));
+        Verify.verify(contexts.putIfAbsent(nodeId, roleContext) == null, "Role context for master Node %s is still not closed.", nodeId);
+        makeDeviceRoleChange(OfpRole.BECOMESLAVE, roleContext, true);
+        notifyListenersRoleInitializationDone(roleContext.getNodeId(), roleContext.initialization());
+        watchingEntities.put(roleContext.getEntity(), roleContext);
+        deviceInitializationPhaseHandler.onDeviceContextLevelUp(nodeId);
     }
 
     @Override
     public void close() {
+        LOG.debug("Close method on role manager was called.");
         entityOwnershipListenerRegistration.close();
         txEntityOwnershipListenerRegistration.close();
         for (final Iterator<RoleContext> iterator = Iterators.consumingIterator(contexts.values().iterator()); iterator.hasNext();) {
             // got here because last known role is LEADER and DS might need clearing up
-            final RoleContext roleCtx = iterator.next();
-            final NodeId nodeId = roleCtx.getDeviceState().getNodeId();
-            if (OfpRole.BECOMEMASTER.equals(roleCtx.getClusterRole())) {
-                LOG.debug("Last role is LEADER and ownershipService returned hasOwner=false for node: {}; "
-                        + "cleaning DS as being probably the last owner", nodeId);
-                removeDeviceFromOperDS(roleCtx);
+            final RoleContext roleContext = iterator.next();
+            watchingEntities.remove(roleContext.getEntity());
+            watchingEntities.remove(roleContext.getTxEntity());
+            contexts.remove(roleContext.getNodeId());
+            if (roleContext.isTxCandidateRegistered()) {
+                LOG.info("Node {} was holder txEntity, so trying to remove device from operational DS.");
+                removeDeviceFromOperationalDS(roleContext.getNodeId());
             } else {
-                // NOOP - there is another owner
-                LOG.debug("Last role is LEADER and ownershipService returned hasOwner=true for node: {}; "
-                        + "leaving DS untouched", nodeId);
+                roleContext.close();
             }
-            txContexts.remove(roleCtx.getTxEntity(), roleCtx);
-            roleCtx.close();
         }
     }
 
     @Override
     public void onDeviceContextLevelDown(final DeviceContext deviceContext) {
-        final NodeId nodeId = deviceContext.getDeviceState().getNodeId();
+        final NodeId nodeId = deviceContext.getPrimaryConnectionContext().getNodeId();
         LOG.trace("onDeviceContextLevelDown for node {}", nodeId);
-        final Entity entity = makeEntity(nodeId);
-        final RoleContext roleContext = contexts.get(entity);
+        final RoleContext roleContext = contexts.get(nodeId);
         if (roleContext != null) {
-            LOG.debug("Found roleContext associated to deviceContext: {}, now closing the roleContext", nodeId);
-            roleContext.terminationRoleContext();
-            final TimerTask timerTask = new TimerTask() {
-
-                @Override
-                public void run(final Timeout timeout) throws Exception {
-                    final RoleContext foundMainRoleCtx = contexts.get(roleContext.getEntity());
-                    final RoleContext foundTxRoleCtx = txContexts.get(roleContext.getTxEntity());
-
-                    if (roleContext.equals(foundMainRoleCtx)) {
-                        LOG.info("OldRoleCtx was not remove for entity {} from contexts", roleContext.getEntity());
-                        contexts.remove(roleContext.getEntity(), roleContext);
-                        foundMainRoleCtx.close();
-                    }
-
-                    if (roleContext.equals(foundTxRoleCtx)) {
-                        LOG.info("OldRoleCtx was not remove for txEntity {} from contexts", roleContext.getTxEntity());
-                        txContexts.remove(roleContext.getTxEntity(), roleContext);
-                        foundTxRoleCtx.close();
-                    }
-                }
-            };
-            deviceContext.getTimer().newTimeout(timerTask, 10, TimeUnit.SECONDS);
+            LOG.debug("Found roleContext associated to deviceContext: {}, now trying close the roleContext", nodeId);
+            if (roleContext.isMainCandidateRegistered()) {
+                roleContext.unregisterCandidate(roleContext.getEntity());
+            } else {
+                contexts.remove(nodeId, roleContext);
+                roleContext.close();
+            }
         }
         deviceTerminationPhaseHandler.onDeviceContextLevelDown(deviceContext);
     }
 
-    private static Entity makeEntity(final NodeId nodeId) {
+    @VisibleForTesting
+    static Entity makeEntity(final NodeId nodeId) {
         return new Entity(RoleManager.ENTITY_TYPE, nodeId.getValue());
     }
 
-    private static Entity makeTxEntity(final NodeId nodeId) {
+    @VisibleForTesting
+    static Entity makeTxEntity(final NodeId nodeId) {
         return new Entity(RoleManager.TX_ENTITY_TYPE, nodeId.getValue());
     }
 
     @Override
     public void ownershipChanged(final EntityOwnershipChange ownershipChange) {
+
         Preconditions.checkArgument(ownershipChange != null);
-        RoleContext roleContext = null;
-        try {
-            roleContext = contexts.get(ownershipChange.getEntity());
-            if (roleContext != null) {
-                changeOwnershipForMainEntity(ownershipChange, roleContext);
-                return;
-            }
+        final RoleContext roleContext = watchingEntities.get(ownershipChange.getEntity());
+
+        LOG.debug("Received EOS message: wasOwner:{} isOwner:{} hasOwner:{} for entity type {} and node {}",
+                ownershipChange.wasOwner(), ownershipChange.isOwner(), ownershipChange.hasOwner(),
+                ownershipChange.getEntity().getType(),
+                roleContext != null ? roleContext.getNodeId() : "-> no watching entity, disregarding notification <-");
 
-            roleContext = txContexts.get(ownershipChange.getEntity());
-            if (roleContext != null) {
+        if (roleContext != null) {
+            if (ownershipChange.getEntity().equals(roleContext.getEntity())) {
+                changeOwnershipForMainEntity(ownershipChange, roleContext);
+            } else {
                 changeOwnershipForTxEntity(ownershipChange, roleContext);
-                return;
-            }
-        } catch (final Exception e) {
-            LOG.warn("fail to acquire semaphore: {}", ownershipChange.getEntity(), e);
-            if (roleContext != null) {
-                roleContext.getDeviceContext().shutdownConnection();
             }
+        } else {
+            LOG.debug("OwnershipChange {}", ownershipChange);
         }
 
-        LOG.debug("We are not able to find Entity {} ownershipChange {} - disregarding ownership notification",
-                ownershipChange.getEntity(), ownershipChange);
     }
 
-    private void changeOwnershipForMainEntity(final EntityOwnershipChange ownershipChange,
-            @CheckForNull final RoleContext roleContext) {
+    @VisibleForTesting
+    void changeOwnershipForMainEntity(final EntityOwnershipChange ownershipChange, final RoleContext roleContext) {
 
-        LOG.debug("Received Main-EntityOwnershipChange:{}", ownershipChange);
-        Preconditions.checkArgument(roleContext != null);
         if (roleContext.isMainCandidateRegistered()) {
-            LOG.debug("Main-EntityOwnershipRegistration is active for entity {}", ownershipChange.getEntity());
+            LOG.debug("Main-EntityOwnershipRegistration is active for entity type {} and node {}",
+                    ownershipChange.getEntity().getType(), roleContext.getNodeId());
             if (!ownershipChange.wasOwner() && ownershipChange.isOwner()) {
                 // SLAVE -> MASTER
-                txContexts.put(roleContext.getTxEntity(), roleContext);
-                roleContext.onDeviceTryToTakeClusterLeadership();
+                LOG.debug("SLAVE to MASTER for node {}", roleContext.getNodeId());
+                if (roleContext.registerCandidate(roleContext.getTxEntity())) {
+                    LOG.debug("Starting watching tx entity for node {}", roleContext.getNodeId());
+                    watchingEntities.putIfAbsent(roleContext.getTxEntity(), roleContext);
+                }
             } else if (ownershipChange.wasOwner() && !ownershipChange.isOwner()) {
                 // MASTER -> SLAVE
-                roleContext.onDeviceLostClusterLeadership();
-            } else if (LOG.isDebugEnabled()) {
-                LOG.debug("Not processed Ownership Main Entity {} Event {}", ownershipChange.getEntity(), ownershipChange);
+                LOG.debug("MASTER to SLAVE for node {}", roleContext.getNodeId());
+                conductor.addOneTimeListenerWhenServicesChangesDone(this, roleContext.getNodeId());
+                makeDeviceRoleChange(OfpRole.BECOMESLAVE, roleContext, false);
             }
         } else {
-            LOG.debug("Main-EntityOwnershipRegistration is not active for entity {}", ownershipChange.getEntity());
-            contexts.remove(ownershipChange.getEntity(), roleContext);
-            if (!ownershipChange.hasOwner() && !ownershipChange.isOwner() && ownershipChange.wasOwner()) {
-                /* Method has to clean all context and registrations */
-                unregistrationHelper(ownershipChange, roleContext);
+            LOG.debug("Main-EntityOwnershipRegistration is not active for entity type {} and node {}",
+                    ownershipChange.getEntity(), roleContext.getNodeId());
+            watchingEntities.remove(ownershipChange.getEntity(), roleContext);
+            if (roleContext.isTxCandidateRegistered()) {
+                LOG.debug("tx candidate still registered for node {}, probably connection lost, trying to unregister tx candidate", roleContext.getNodeId());
+                roleContext.unregisterCandidate(roleContext.getTxEntity());
+                if (ownershipChange.wasOwner() && !ownershipChange.isOwner() && !ownershipChange.hasOwner()) {
+                    LOG.debug("Trying to remove from operational node: {}", roleContext.getNodeId());
+                    removeDeviceFromOperationalDS(roleContext.getNodeId());
+                }
             } else {
-                txContexts.remove(roleContext.getTxEntity(), roleContext);
+                final NodeId nodeId = roleContext.getNodeId();
+                contexts.remove(nodeId, roleContext);
                 roleContext.close();
+                conductor.closeConnection(nodeId);
             }
         }
     }
 
-    private void changeOwnershipForTxEntity(final EntityOwnershipChange ownershipChange,
+    @VisibleForTesting
+    void changeOwnershipForTxEntity(final EntityOwnershipChange ownershipChange,
             @Nonnull final RoleContext roleContext) {
 
-        LOG.debug("Received TX-EntityOwnershipChange:{}", ownershipChange);
-        Preconditions.checkArgument(roleContext != null);
         if (roleContext.isTxCandidateRegistered()) {
-            LOG.debug("Tx-EntityOwnershipRegistration is active for entity {}", ownershipChange.getEntity());
+            LOG.debug("Tx-EntityOwnershipRegistration is active for entity type {} and node {}",
+                    ownershipChange.getEntity().getType(),
+                    roleContext.getNodeId());
             if (!ownershipChange.wasOwner() && ownershipChange.isOwner()) {
                 // SLAVE -> MASTER
-                roleContext.onDeviceTakeClusterLeadership();
+                LOG.debug("SLAVE to MASTER for node {}", roleContext.getNodeId());
+                makeDeviceRoleChange(OfpRole.BECOMEMASTER, roleContext,false);
             } else if (ownershipChange.wasOwner() && !ownershipChange.isOwner()) {
                 // MASTER -> SLAVE
-                LOG.warn("Tx-EntityOwnershipRegistration unexpected lost Leadership entity {}", ownershipChange.getEntity());
-                roleContext.getDeviceContext().shutdownConnection();
-            } else {
-                LOG.debug("NOOP state transition for TxEntity {} ", roleContext.getTxEntity());
+                LOG.debug("MASTER to SLAVE for node {}", roleContext.getNodeId());
+                LOG.warn("Tx-EntityOwnershipRegistration lost leadership entity type {} and node {}",
+                        ownershipChange.getEntity().getType(),roleContext.getNodeId());
+                watchingEntities.remove(roleContext.getTxEntity(), roleContext);
+                watchingEntities.remove(roleContext.getEntity(), roleContext);
+                roleContext.unregisterCandidate(roleContext.getEntity());
+                roleContext.unregisterCandidate(roleContext.getTxEntity());
+                if (!ownershipChange.hasOwner()) {
+                    LOG.debug("Trying to remove from operational node: {}", roleContext.getNodeId());
+                    removeDeviceFromOperationalDS(roleContext.getNodeId());
+                } else {
+                    final NodeId nodeId = roleContext.getNodeId();
+                    contexts.remove(nodeId, roleContext);
+                    roleContext.close();
+                    conductor.closeConnection(nodeId);
+                }
             }
         } else {
-            LOG.debug("Tx-EntityOwnershipRegistration is not active for entity {}", ownershipChange.getEntity());
-            txContexts.remove(ownershipChange.getEntity(), roleContext);
+            LOG.debug("Tx-EntityOwnershipRegistration is not active for entity {}", ownershipChange.getEntity().getType());
+            watchingEntities.remove(roleContext.getTxEntity(), roleContext);
+            final NodeId nodeId = roleContext.getNodeId();
+            contexts.remove(nodeId, roleContext);
+            roleContext.close();
+            conductor.closeConnection(nodeId);
         }
     }
 
-    private CheckedFuture<Void, TransactionCommitFailedException> removeDeviceFromOperDS(
-            final RoleChangeListener roleChangeListener) {
-        Preconditions.checkArgument(roleChangeListener != null);
-        final DeviceState deviceState = roleChangeListener.getDeviceState();
-        final WriteTransaction delWtx = dataBroker.newWriteOnlyTransaction();
-        delWtx.delete(LogicalDatastoreType.OPERATIONAL, deviceState.getNodeInstanceIdentifier());
-        final CheckedFuture<Void, TransactionCommitFailedException> delFuture = delWtx.submit();
-        Futures.addCallback(delFuture, new FutureCallback<Void>() {
-
+    @VisibleForTesting
+    void makeDeviceRoleChange(final OfpRole role, final RoleContext roleContext, final Boolean init) {
+        final ListenableFuture<RpcResult<SetRoleOutput>> roleChangeFuture = sendRoleChangeToDevice(role, roleContext);
+        Futures.addCallback(roleChangeFuture, new FutureCallback<RpcResult<SetRoleOutput>>() {
             @Override
-            public void onSuccess(final Void result) {
-                LOG.debug("Delete Node {} was successful", deviceState.getNodeId());
+            public void onSuccess(@Nullable final RpcResult<SetRoleOutput> setRoleOutputRpcResult) {
+                LOG.info("Role {} successfully set on device {}", role, roleContext.getNodeId());
+                notifyListenersRoleChangeOnDevice(roleContext.getNodeId(), true, role, init);
             }
 
             @Override
-            public void onFailure(final Throwable t) {
-                LOG.warn("Delete Node {} failed.", deviceState.getNodeId(), t);
+            public void onFailure(@Nonnull final Throwable throwable) {
+                LOG.warn("Unable to set role {} on device {}", role, roleContext.getNodeId());
+                notifyListenersRoleChangeOnDevice(roleContext.getNodeId(), false, role, init);
             }
         });
-        return delFuture;
     }
 
-    private void unregistrationHelper(final EntityOwnershipChange ownershipChange, final RoleContext roleContext) {
-        LOG.info("Initiate removal from operational. Possibly the last node to be disconnected for :{}. ",
-                ownershipChange);
-        Futures.addCallback(removeDeviceFromOperDS(roleContext), new FutureCallback<Void>() {
+
+    private ListenableFuture<RpcResult<SetRoleOutput>> sendRoleChangeToDevice(final OfpRole newRole, final RoleContext roleContext) {
+        LOG.debug("Sending new role {} to device {}", newRole, roleContext.getNodeId());
+        final Future<RpcResult<SetRoleOutput>> setRoleOutputFuture;
+        final Short version = conductor.gainVersionSafely(roleContext.getNodeId());
+        if (null == version) {
+            LOG.debug("Device version is null");
+            return Futures.immediateFuture(null);
+        }
+        if (version < OFConstants.OFP_VERSION_1_3) {
+            LOG.debug("Device version not support ROLE");
+            return Futures.immediateFuture(null);
+        } else {
+            final SetRoleInput setRoleInput = (new SetRoleInputBuilder()).setControllerRole(newRole)
+                    .setNode(new NodeRef(DeviceStateUtil.createNodeInstanceIdentifier(roleContext.getNodeId()))).build();
+            setRoleOutputFuture = roleContext.getSalRoleService().setRole(setRoleInput);
+            final TimerTask timerTask = new TimerTask() {
+
+                @Override
+                public void run(final Timeout timeout) throws Exception {
+                    if (!setRoleOutputFuture.isDone()) {
+                        LOG.warn("New role {} was not propagated to device {} during 10 sec", newRole, roleContext.getNodeId());
+                        setRoleOutputFuture.cancel(true);
+                    }
+                }
+            };
+            conductor.newTimeout(timerTask, 10, TimeUnit.SECONDS);
+        }
+        return JdkFutureAdapters.listenInPoolThread(setRoleOutputFuture);
+    }
+
+    @VisibleForTesting
+    CheckedFuture<Void, TransactionCommitFailedException> removeDeviceFromOperationalDS(final NodeId nodeId) {
+
+        final WriteTransaction delWtx = dataBroker.newWriteOnlyTransaction();
+        delWtx.delete(LogicalDatastoreType.OPERATIONAL, DeviceStateUtil.createNodeInstanceIdentifier(nodeId));
+        final CheckedFuture<Void, TransactionCommitFailedException> delFuture = delWtx.submit();
+        Futures.addCallback(delFuture, new FutureCallback<Void>() {
+
             @Override
-            public void onSuccess(final Void aVoid) {
-                LOG.debug("Removing context for device: {}", roleContext.getDeviceState().getNodeId());
-                txContexts.remove(roleContext.getTxEntity(), roleContext);
-                roleContext.close();
+            public void onSuccess(final Void result) {
+                LOG.debug("Delete Node {} was successful", nodeId);
+                final RoleContext roleContext = contexts.remove(nodeId);
+                if (roleContext != null) {
+                    roleContext.close();
+                }
             }
 
             @Override
-            public void onFailure(final Throwable throwable) {
-                LOG.warn("Removing role context for device: {}, but {}", roleContext.getDeviceState().getNodeId(),
-                        throwable.getMessage());
-                txContexts.remove(roleContext.getTxEntity(), roleContext);
-                roleContext.close();
+            public void onFailure(@Nonnull final Throwable t) {
+                LOG.warn("Delete Node {} failed. {}", nodeId, t);
+                contexts.remove(nodeId);
+                final RoleContext roleContext = contexts.remove(nodeId);
+                if (roleContext != null) {
+                    roleContext.close();
+                }
             }
         });
+        return delFuture;
     }
 
     @Override
     public void setDeviceTerminationPhaseHandler(final DeviceTerminationPhaseHandler handler) {
         deviceTerminationPhaseHandler = handler;
     }
+
+    @Override
+    public void servicesChangeDone(final NodeId nodeId, final boolean success) {
+        LOG.debug("Services stopping done for node {} as " + (success ? "successful" : "unsuccessful"), nodeId);
+        final RoleContext roleContext = contexts.get(nodeId);
+        if (null != roleContext) {
+            /* Services stopped or failure */
+            roleContext.unregisterCandidate(roleContext.getTxEntity());
+        }
+    }
+
+    @VisibleForTesting
+    RoleContext getRoleContext(final NodeId nodeId){
+        return contexts.get(nodeId);
+    }
+
+    @Override
+    public void addRoleChangeListener(final RoleChangeListener roleChangeListener) {
+        this.listeners.add(roleChangeListener);
+    }
+
+    /**
+     * Invoked when initialization phase is done
+     * @param nodeId node identification
+     * @param success true if initialization done ok, false otherwise
+     */
+    @VisibleForTesting
+    void notifyListenersRoleInitializationDone(final NodeId nodeId, final boolean success){
+        LOG.debug("Notifying registered listeners for role initialization done, no. of listeners {}", listeners.size());
+        for (final RoleChangeListener listener : listeners) {
+            listener.roleInitializationDone(nodeId, success);
+        }
+    }
+
+    /**
+     * Notifies registered listener on role change. Role is the new role on device
+     * If initialization phase is true, we may skip service starting
+     * @param success true if role change on device done ok, false otherwise
+     * @param role new role meant to be set on device
+     * @param initializationPhase if true, then skipp services start
+     */
+    @VisibleForTesting
+    void notifyListenersRoleChangeOnDevice(final NodeId nodeId, final boolean success, final OfpRole role, final boolean initializationPhase){
+        LOG.debug("Notifying registered listeners for role change, no. of listeners {}", listeners.size());
+        for (final RoleChangeListener listener : listeners) {
+            listener.roleChangeOnDevice(nodeId, success, role, initializationPhase);
+        }
+    }
+
 }
index 3179038cc87fed1876c270860bf1e67522525079..bc3545bb9ac178f5f605bd73f3a3381f00054fd1 100644 (file)
@@ -14,17 +14,18 @@ import java.util.Map.Entry;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.ConcurrentMap;
 import java.util.concurrent.Semaphore;
-import java.util.concurrent.atomic.AtomicLong;
-import com.google.common.base.Preconditions;
-import org.opendaylight.controller.md.sal.binding.api.NotificationPublishService;
+
 import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.RoutedRpcRegistration;
 import org.opendaylight.controller.sal.binding.api.RpcProviderRegistry;
-import org.opendaylight.openflowplugin.api.openflow.device.DeviceContext;
 import org.opendaylight.openflowplugin.api.openflow.device.RequestContext;
+import org.opendaylight.openflowplugin.api.openflow.device.XidSequencer;
 import org.opendaylight.openflowplugin.api.openflow.rpc.RpcContext;
 import org.opendaylight.openflowplugin.api.openflow.statistics.ofpspecific.MessageSpy;
-import org.opendaylight.openflowplugin.impl.util.MdSalRegistrationUtils;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeContext;
+import org.opendaylight.controller.md.sal.binding.api.NotificationPublishService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
+import org.opendaylight.yangtools.yang.binding.KeyedInstanceIdentifier;
 import org.opendaylight.yangtools.yang.binding.RpcService;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -32,25 +33,25 @@ import org.slf4j.LoggerFactory;
 public class RpcContextImpl implements RpcContext {
     private static final Logger LOG = LoggerFactory.getLogger(RpcContextImpl.class);
     private final RpcProviderRegistry rpcProviderRegistry;
-    private final DeviceContext deviceContext;
     private final MessageSpy messageSpy;
     private final Semaphore tracker;
+    private final XidSequencer xidSequencer;
 
     // TODO: add private Sal salBroker
     private final ConcurrentMap<Class<?>, RoutedRpcRegistration<?>> rpcRegistrations = new ConcurrentHashMap<>();
-    private final boolean isStatisticsRpcEnabled;
-    private final NotificationPublishService notificationPublishService;
+    private final KeyedInstanceIdentifier<Node, NodeKey> nodeInstanceIdentifier;
 
-    public RpcContextImpl(final MessageSpy messageSpy, final RpcProviderRegistry rpcProviderRegistry, final DeviceContext deviceContext,
-            final int maxRequests, final boolean isStatisticsRpcEnabled,
-            final NotificationPublishService notificationPublishService) {
-        this.deviceContext = Preconditions.checkNotNull(deviceContext);
+    public RpcContextImpl(final RpcProviderRegistry rpcProviderRegistry,
+                          final XidSequencer xidSequencer,
+                          final MessageSpy messageSpy,
+                          final int maxRequests,
+                          final KeyedInstanceIdentifier<Node, NodeKey> nodeInstanceIdentifier) {
+        this.xidSequencer = Preconditions.checkNotNull(xidSequencer);
         this.messageSpy = Preconditions.checkNotNull(messageSpy);
         this.rpcProviderRegistry = Preconditions.checkNotNull(rpcProviderRegistry);
-        this.isStatisticsRpcEnabled = isStatisticsRpcEnabled;
-        this.notificationPublishService = notificationPublishService;
+        this.nodeInstanceIdentifier = nodeInstanceIdentifier;
+
         tracker = new Semaphore(maxRequests, true);
-        deviceContext.setRpcContext(RpcContextImpl.this);
     }
 
     /**
@@ -60,20 +61,12 @@ public class RpcContextImpl implements RpcContext {
     @Override
     public <S extends RpcService> void registerRpcServiceImplementation(final Class<S> serviceClass,
                                                                         final S serviceInstance) {
-        LOG.trace("Try to register service {} for device {}.", serviceClass, deviceContext.getDeviceState().getNodeInstanceIdentifier());
+        LOG.trace("Try to register service {} for device {}.", serviceClass, nodeInstanceIdentifier);
         if (! rpcRegistrations.containsKey(serviceClass)) {
             final RoutedRpcRegistration<S> routedRpcReg = rpcProviderRegistry.addRoutedRpcImplementation(serviceClass, serviceInstance);
-            routedRpcReg.registerPath(NodeContext.class, deviceContext.getDeviceState().getNodeInstanceIdentifier());
+            routedRpcReg.registerPath(NodeContext.class, nodeInstanceIdentifier);
             rpcRegistrations.put(serviceClass, routedRpcReg);
-            LOG.debug("Registration of service {} for device {}.", serviceClass, deviceContext.getDeviceState().getNodeInstanceIdentifier());
-        }
-    }
-
-    @Override
-    public void registerStatCompatibilityServices() {
-        if (isStatisticsRpcEnabled) {
-            MdSalRegistrationUtils.registerStatCompatibilityServices(RpcContextImpl.this, deviceContext,
-                    notificationPublishService, new AtomicLong());
+            LOG.debug("Registration of service {} for device {}.", serviceClass, nodeInstanceIdentifier);
         }
     }
 
@@ -82,6 +75,7 @@ public class RpcContextImpl implements RpcContext {
         final RpcService rpcService = rpcRegistrations.get(serviceClass).getInstance();
         return (S) rpcService;
     }
+
     /**
      * Unregisters all services.
      *
@@ -92,10 +86,10 @@ public class RpcContextImpl implements RpcContext {
         for (final Iterator<Entry<Class<?>, RoutedRpcRegistration<?>>> iterator = Iterators
                 .consumingIterator(rpcRegistrations.entrySet().iterator()); iterator.hasNext();) {
             final RoutedRpcRegistration<?> rpcRegistration = iterator.next().getValue();
-            rpcRegistration.unregisterPath(NodeContext.class, deviceContext.getDeviceState().getNodeInstanceIdentifier());
+            rpcRegistration.unregisterPath(NodeContext.class, nodeInstanceIdentifier);
             rpcRegistration.close();
             LOG.debug("Closing RPC Registration of service {} for device {}.", rpcRegistration.getServiceType(),
-                    deviceContext.getDeviceState().getNodeInstanceIdentifier());
+                    nodeInstanceIdentifier);
         }
     }
 
@@ -105,12 +99,12 @@ public class RpcContextImpl implements RpcContext {
             LOG.trace("Device queue {} at capacity", this);
             return null;
         } else {
-            LOG.trace("Acquired semaphore for {}, available permits:{} ", deviceContext.getDeviceState().getNodeId(), tracker.availablePermits());
+            LOG.trace("Acquired semaphore for {}, available permits:{} ", nodeInstanceIdentifier.getKey().getId(), tracker.availablePermits());
         }
 
-        final Long xid = deviceContext.reservedXidForDeviceMessage();
+        final Long xid = xidSequencer.reserveXidForDeviceMessage();
         if (xid == null) {
-            LOG.warn("Xid cannot be reserved for new RequestContext, node:{}", deviceContext.getDeviceState().getNodeId());
+            LOG.warn("Xid cannot be reserved for new RequestContext, node:{}", nodeInstanceIdentifier.getKey().getId());
             tracker.release();
             return null;
         }
@@ -128,12 +122,12 @@ public class RpcContextImpl implements RpcContext {
 
     @Override
     public <S extends RpcService> void unregisterRpcServiceImplementation(final Class<S> serviceClass) {
-        LOG.trace("Try to unregister serviceClass {} for Node {}", serviceClass, deviceContext.getDeviceState().getNodeId());
+        LOG.trace("Try to unregister serviceClass {} for Node {}", serviceClass, nodeInstanceIdentifier.getKey().getId());
         final RoutedRpcRegistration<?> rpcRegistration = rpcRegistrations.remove(serviceClass);
         if (rpcRegistration != null) {
-            rpcRegistration.unregisterPath(NodeContext.class, deviceContext.getDeviceState().getNodeInstanceIdentifier());
+            rpcRegistration.unregisterPath(NodeContext.class, nodeInstanceIdentifier);
             rpcRegistration.close();
-            LOG.debug("Unregistration serviceClass {} for Node {}", serviceClass, deviceContext.getDeviceState().getNodeId());
+            LOG.debug("Unregistration serviceClass {} for Node {}", serviceClass, nodeInstanceIdentifier.getKey().getId());
         }
     }
 }
index 61b114056d1e4e9be5f672bc92ba39791f633f82..063ea26ef08ea1bd94244572241a863b9e820133 100644 (file)
@@ -7,6 +7,7 @@
  */
 package org.opendaylight.openflowplugin.impl.rpc;
 
+import com.google.common.base.Preconditions;
 import com.google.common.base.Verify;
 import com.google.common.collect.Iterators;
 import java.util.Iterator;
@@ -17,11 +18,10 @@ import org.opendaylight.controller.sal.binding.api.RpcProviderRegistry;
 import org.opendaylight.openflowplugin.api.openflow.device.DeviceContext;
 import org.opendaylight.openflowplugin.api.openflow.device.handlers.DeviceInitializationPhaseHandler;
 import org.opendaylight.openflowplugin.api.openflow.device.handlers.DeviceTerminationPhaseHandler;
+import org.opendaylight.openflowplugin.api.openflow.lifecycle.LifecycleConductor;
 import org.opendaylight.openflowplugin.api.openflow.rpc.RpcContext;
 import org.opendaylight.openflowplugin.api.openflow.rpc.RpcManager;
-import org.opendaylight.openflowplugin.impl.util.MdSalRegistrationUtils;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.role.service.rev150727.OfpRole;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -33,13 +33,15 @@ public class RpcManagerImpl implements RpcManager {
     private DeviceTerminationPhaseHandler deviceTerminPhaseHandler;
     private final int maxRequestsQuota;
     private final ConcurrentMap<NodeId, RpcContext> contexts = new ConcurrentHashMap<>();
-    private boolean isStatisticsRpcEnabled;
-    private NotificationPublishService notificationPublishService;
+
+    private final LifecycleConductor conductor;
 
     public RpcManagerImpl(final RpcProviderRegistry rpcProviderRegistry,
-                          final int quotaValue) {
+                          final int quotaValue,
+                          final LifecycleConductor lifecycleConductor) {
         this.rpcProviderRegistry = rpcProviderRegistry;
         maxRequestsQuota = quotaValue;
+        this.conductor = lifecycleConductor;
     }
 
     @Override
@@ -48,33 +50,23 @@ public class RpcManagerImpl implements RpcManager {
     }
 
     @Override
-    public void onDeviceContextLevelUp(final DeviceContext deviceContext) throws Exception {
-        final NodeId nodeId = deviceContext.getDeviceState().getNodeId();
-        final OfpRole ofpRole = deviceContext.getDeviceState().getRole();
+    public void onDeviceContextLevelUp(final NodeId nodeId) throws Exception {
 
-        LOG.debug("Node:{}, deviceContext.getDeviceState().getRole():{}", nodeId, ofpRole);
-        final RpcContext rpcContext = new RpcContextImpl(deviceContext.getMessageSpy(), rpcProviderRegistry,
-                deviceContext, maxRequestsQuota, isStatisticsRpcEnabled, notificationPublishService);
+        final DeviceContext deviceContext = Preconditions.checkNotNull(conductor.getDeviceContext(nodeId));
 
-        Verify.verify(contexts.putIfAbsent(nodeId, rpcContext) == null, "RpcCtx still not closed for node {}", nodeId);
-        deviceContext.addDeviceContextClosedHandler(this);
+        final RpcContext rpcContext = new RpcContextImpl(
+                rpcProviderRegistry,
+                deviceContext,
+                deviceContext.getMessageSpy(),
+                maxRequestsQuota,
+                deviceContext.getDeviceState().getNodeInstanceIdentifier());
 
-        if (OfpRole.BECOMEMASTER.equals(ofpRole)) {
-            LOG.info("Registering Openflow Master RPCs for node:{}, role:{}", nodeId, ofpRole);
-            MdSalRegistrationUtils.registerMasterServices(rpcContext, deviceContext, ofpRole);
+        deviceContext.setRpcContext(rpcContext);
 
-        } else if(OfpRole.BECOMESLAVE.equals(ofpRole)) {
-            // if slave, we need to de-register rpcs if any have been registered, in case of master to slave
-            LOG.info("Unregister RPC services (if any) for slave role for node:{}", deviceContext.getDeviceState().getNodeId());
-            MdSalRegistrationUtils.registerSlaveServices(rpcContext, ofpRole);
-        } else {
-            // if we don't know role, we need to unregister rpcs if any have been registered
-            LOG.info("Unregister RPC services (if any) for slave role for node:{}", deviceContext.getDeviceState().getNodeId());
-            MdSalRegistrationUtils.unregisterServices(rpcContext);
-        }
+        Verify.verify(contexts.putIfAbsent(nodeId, rpcContext) == null, "RpcCtx still not closed for node {}", nodeId);
 
         // finish device initialization cycle back to DeviceManager
-        deviceInitPhaseHandler.onDeviceContextLevelUp(deviceContext);
+        deviceInitPhaseHandler.onDeviceContextLevelUp(nodeId);
     }
 
     @Override
@@ -85,7 +77,6 @@ public class RpcManagerImpl implements RpcManager {
         }
     }
 
-
     @Override
     public void onDeviceContextLevelDown(final DeviceContext deviceContext) {
         final RpcContext removedContext = contexts.remove(deviceContext.getDeviceState().getNodeId());
@@ -95,15 +86,6 @@ public class RpcManagerImpl implements RpcManager {
         }
         deviceTerminPhaseHandler.onDeviceContextLevelDown(deviceContext);
     }
-    @Override
-    public void setStatisticsRpcEnabled(final boolean isStatisticsRpcEnabled) {
-        this.isStatisticsRpcEnabled = isStatisticsRpcEnabled;
-    }
-
-    @Override
-    public void setNotificationPublishService(final NotificationPublishService notificationPublishService) {
-        this.notificationPublishService = notificationPublishService;
-    }
 
     @Override
     public void setDeviceTerminationPhaseHandler(final DeviceTerminationPhaseHandler handler) {
index f35abc9e30fd66f109f66ecc134e6833aac5d38d..018f1f10108041149a9d119030e9f74441c1c291 100644 (file)
@@ -15,12 +15,16 @@ import org.opendaylight.yangtools.yang.binding.DataObject;
 import org.opendaylight.yangtools.yang.binding.Identifiable;
 import org.opendaylight.yangtools.yang.binding.Identifier;
 import org.opendaylight.yangtools.yang.binding.KeyedInstanceIdentifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 /**
  * General implementation of {@link ItemLifecycleListener} - keeping of DS/operational reflection up-to-date
  */
 public class ItemLifecycleListenerImpl implements ItemLifecycleListener {
 
+    private static final Logger LOG = LoggerFactory.getLogger(ItemLifecycleListenerImpl.class);
+
     private final DeviceContext deviceContext;
 
     public ItemLifecycleListenerImpl(DeviceContext deviceContext) {
@@ -29,13 +33,21 @@ public class ItemLifecycleListenerImpl implements ItemLifecycleListener {
 
     @Override
     public <I extends Identifiable<K> & DataObject, K extends Identifier<I>> void onAdded(KeyedInstanceIdentifier<I, K> itemPath, I itemBody) {
-        deviceContext.writeToTransaction(LogicalDatastoreType.OPERATIONAL, itemPath, itemBody);
-        deviceContext.submitTransaction();
+        try {
+            deviceContext.writeToTransaction(LogicalDatastoreType.OPERATIONAL, itemPath, itemBody);
+            deviceContext.submitTransaction();
+        } catch (Exception e) {
+            LOG.warn("Not able to write to transaction: {}", e.getMessage());
+        }
     }
 
     @Override
     public <I extends Identifiable<K> & DataObject, K extends Identifier<I>> void onRemoved(KeyedInstanceIdentifier<I, K> itemPath) {
-        deviceContext.addDeleteToTxChain(LogicalDatastoreType.OPERATIONAL, itemPath);
-        deviceContext.submitTransaction();
+        try {
+            deviceContext.addDeleteToTxChain(LogicalDatastoreType.OPERATIONAL, itemPath);
+            deviceContext.submitTransaction();
+        } catch (Exception e) {
+            LOG.warn("Not able to write to transaction: {}", e.getMessage());
+        }
     }
 }
index 1a3c104b39079b2d55406839b479c8e3e20603f5..1c218b37b2c4a56eec0b2c1ae91fc2ec9449c117 100644 (file)
@@ -80,7 +80,11 @@ public final class SalTableServiceImpl extends AbstractMultipartService<UpdateTa
                         final UpdateTableOutputBuilder updateTableOutputBuilder = new UpdateTableOutputBuilder();
                         updateTableOutputBuilder.setTransactionId(new TransactionId(BigInteger.valueOf(xid)));
                         finalFuture.set(RpcResultBuilder.success(updateTableOutputBuilder.build()).build());
-                        writeResponseToOperationalDatastore(multipartReplies);
+                        try {
+                            writeResponseToOperationalDatastore(multipartReplies);
+                        } catch (Exception e) {
+                            LOG.warn("Not able to write to operational datastore: {}", e.getMessage());
+                        }
                     }
                 } else {
                     LOG.debug("OnSuccess, rpc result unsuccessful, multipart response for rpc update-table was unsuccessful.");
@@ -105,7 +109,7 @@ public final class SalTableServiceImpl extends AbstractMultipartService<UpdateTa
     /**
      * @param multipartReplies
      */
-    private void writeResponseToOperationalDatastore(final List<MultipartReply> multipartReplies) {
+    private void writeResponseToOperationalDatastore(final List<MultipartReply> multipartReplies) throws Exception {
 
         final List<org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.table.features.TableFeatures> salTableFeatures = convertToSalTableFeatures(multipartReplies);
 
index ea09df7573e0615c5578fade4d1b531c91251ce1..e02633ae77197d71059ce18afd5033e1ff6302e3 100644 (file)
@@ -24,12 +24,14 @@ import java.util.HashSet;
 import java.util.Iterator;
 import java.util.List;
 import javax.annotation.CheckForNull;
+import javax.annotation.Nonnull;
 import javax.annotation.Nullable;
 import javax.annotation.concurrent.GuardedBy;
 import org.opendaylight.openflowplugin.api.openflow.connection.ConnectionContext;
 import org.opendaylight.openflowplugin.api.openflow.device.DeviceContext;
 import org.opendaylight.openflowplugin.api.openflow.device.DeviceState;
 import org.opendaylight.openflowplugin.api.openflow.device.RequestContext;
+import org.opendaylight.openflowplugin.api.openflow.lifecycle.LifecycleConductor;
 import org.opendaylight.openflowplugin.api.openflow.rpc.listener.ItemLifecycleListener;
 import org.opendaylight.openflowplugin.api.openflow.statistics.StatisticsContext;
 import org.opendaylight.openflowplugin.impl.rpc.AbstractRequestContext;
@@ -37,13 +39,11 @@ import org.opendaylight.openflowplugin.impl.rpc.listener.ItemLifecycleListenerIm
 import org.opendaylight.openflowplugin.impl.services.RequestContextUtil;
 import org.opendaylight.openflowplugin.impl.statistics.services.dedicated.StatisticsGatheringOnTheFlyService;
 import org.opendaylight.openflowplugin.impl.statistics.services.dedicated.StatisticsGatheringService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.MultipartType;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-/**
- * Created by Martin Bobak &lt;mbobak@cisco.com&gt; on 1.4.2015.
- */
 public class StatisticsContextImpl implements StatisticsContext {
 
     private static final Logger LOG = LoggerFactory.getLogger(StatisticsContextImpl.class);
@@ -63,12 +63,14 @@ public class StatisticsContextImpl implements StatisticsContext {
     private StatisticsGatheringOnTheFlyService statisticsGatheringOnTheFlyService;
     private Timeout pollTimeout;
 
-    public StatisticsContextImpl(@CheckForNull final DeviceContext deviceContext,
-            final boolean shuttingDownStatisticsPolling) {
-        this.deviceContext = Preconditions.checkNotNull(deviceContext);
+    private final LifecycleConductor conductor;
+
+    public StatisticsContextImpl(@CheckForNull final NodeId nodeId, final boolean shuttingDownStatisticsPolling, final LifecycleConductor lifecycleConductor) {
+        this.conductor = lifecycleConductor;
+        this.deviceContext = Preconditions.checkNotNull(conductor.getDeviceContext(nodeId));
         this.devState = Preconditions.checkNotNull(deviceContext.getDeviceState());
         this.shuttingDownStatisticsPolling = shuttingDownStatisticsPolling;
-        emptyFuture = Futures.immediateFuture(new Boolean(false));
+        emptyFuture = Futures.immediateFuture(false);
         statisticsGatheringService = new StatisticsGatheringService(this, deviceContext);
         statisticsGatheringOnTheFlyService = new StatisticsGatheringOnTheFlyService(this, deviceContext);
         itemLifeCycleListener = new ItemLifecycleListenerImpl(deviceContext);
@@ -165,7 +167,7 @@ public class StatisticsContextImpl implements StatisticsContext {
 
     @Override
     public <T> RequestContext<T> createRequestContext() {
-        final AbstractRequestContext<T> ret = new AbstractRequestContext<T>(deviceContext.reservedXidForDeviceMessage()) {
+        final AbstractRequestContext<T> ret = new AbstractRequestContext<T>(deviceContext.reserveXidForDeviceMessage()) {
             @Override
             public void close() {
                 requestContexts.remove(this);
@@ -186,121 +188,118 @@ public class StatisticsContextImpl implements StatisticsContext {
             }
         }
 
-        @Override
-        public void setPollTimeout (Timeout pollTimeout){
-            this.pollTimeout = pollTimeout;
-        }
+    @Override
+    public void setPollTimeout(final Timeout pollTimeout) {
+        this.pollTimeout = pollTimeout;
+    }
 
-        @Override
-        public Optional<Timeout> getPollTimeout () {
-            return Optional.fromNullable(pollTimeout);
+    @Override
+    public Optional<Timeout> getPollTimeout() {
+        return Optional.fromNullable(pollTimeout);
+    }
+
+    private void statChainFuture(final Iterator<MultipartType> iterator, final SettableFuture<Boolean> resultFuture) {
+        if (ConnectionContext.CONNECTION_STATE.RIP.equals(deviceContext.getPrimaryConnectionContext().getConnectionState())) {
+            final String errMsg = String.format("Device connection is closed for Node : %s.",
+                    deviceContext.getDeviceState().getNodeId());
+            LOG.debug(errMsg);
+            resultFuture.setException(new IllegalStateException(errMsg));
+            return;
+        }
+        if ( ! iterator.hasNext()) {
+            resultFuture.set(Boolean.TRUE);
+            LOG.debug("Stats collection successfully finished for node {}", deviceContext.getDeviceState().getNodeId());
+            return;
         }
 
-        void statChainFuture ( final Iterator<MultipartType> iterator, final SettableFuture<Boolean> resultFuture){
+        final MultipartType nextType = iterator.next();
+        LOG.debug("Stats iterating to next type for node {} of type {}", deviceContext.getDeviceState().getNodeId(), nextType);
 
-            if (ConnectionContext.CONNECTION_STATE.RIP.equals(deviceContext.getPrimaryConnectionContext().getConnectionState())) {
-                final String errMsg = String.format("Device connection is closed for Node : %s.",
-                        deviceContext.getDeviceState().getNodeId());
-                LOG.debug(errMsg);
-                resultFuture.setException(new IllegalStateException(errMsg));
-                return;
+        final ListenableFuture<Boolean> deviceStatisticsCollectionFuture = chooseStat(nextType);
+        Futures.addCallback(deviceStatisticsCollectionFuture, new FutureCallback<Boolean>() {
+            @Override
+            public void onSuccess(final Boolean result) {
+                statChainFuture(iterator, resultFuture);
             }
-
-            if (!iterator.hasNext()) {
-                resultFuture.set(Boolean.TRUE);
-                LOG.debug("Stats collection successfully finished for node {}", deviceContext.getDeviceState().getNodeId());
-                return;
+            @Override
+            public void onFailure(@Nonnull final Throwable t) {
+                resultFuture.setException(t);
             }
+        });
+    }
 
-            final MultipartType nextType = iterator.next();
-            LOG.debug("Stats iterating to next type for node {} of type {}", deviceContext.getDeviceState().getNodeId(), nextType);
-
-            final ListenableFuture<Boolean> deviceStatisticsCollectionFuture = chooseStat(nextType);
-            Futures.addCallback(deviceStatisticsCollectionFuture, new FutureCallback<Boolean>() {
-                @Override
-                public void onSuccess(final Boolean result) {
-                    statChainFuture(iterator, resultFuture);
-                }
-
-                @Override
-                public void onFailure(final Throwable t) {
-                    resultFuture.setException(t);
-                }
-            });
-        }
-
-        /**
-         * Method checks a device state. It returns null for be able continue. Otherwise it returns immediateFuture
-         * which has to be returned from caller too
-         *
-         * @return
-         */
-        @VisibleForTesting
-        ListenableFuture<Boolean> deviceConnectionCheck () {
-            if (!ConnectionContext.CONNECTION_STATE.WORKING.equals(deviceContext.getPrimaryConnectionContext().getConnectionState())) {
-                ListenableFuture<Boolean> resultingFuture = SettableFuture.create();
-                switch (deviceContext.getPrimaryConnectionContext().getConnectionState()) {
-                    case RIP:
-                        final String errMsg = String.format("Device connection doesn't exist anymore. Primary connection status : %s",
-                                deviceContext.getPrimaryConnectionContext().getConnectionState());
-                        resultingFuture = Futures.immediateFailedFuture(new Throwable(errMsg));
-                        break;
-                    default:
-                        resultingFuture = Futures.immediateCheckedFuture(Boolean.TRUE);
-                        break;
-                }
-                return resultingFuture;
+    /**
+     * Method checks a device state. It returns null for be able continue. Otherwise it returns immediateFuture
+     * which has to be returned from caller too
+     *
+     * @return
+     */
+    @VisibleForTesting
+    ListenableFuture<Boolean> deviceConnectionCheck() {
+        if (!ConnectionContext.CONNECTION_STATE.WORKING.equals(deviceContext.getPrimaryConnectionContext().getConnectionState())) {
+            ListenableFuture<Boolean> resultingFuture = SettableFuture.create();
+            switch (deviceContext.getPrimaryConnectionContext().getConnectionState()) {
+                case RIP:
+                    final String errMsg = String.format("Device connection doesn't exist anymore. Primary connection status : %s",
+                            deviceContext.getPrimaryConnectionContext().getConnectionState());
+                    resultingFuture = Futures.immediateFailedFuture(new Throwable(errMsg));
+                    break;
+                default:
+                    resultingFuture = Futures.immediateCheckedFuture(Boolean.TRUE);
+                    break;
             }
-            return null;
+            return resultingFuture;
         }
+        return null;
+    }
 
-        private ListenableFuture<Boolean> collectFlowStatistics ( final MultipartType multipartType){
-            return devState.isFlowStatisticsAvailable() ? StatisticsGatheringUtils.gatherStatistics(
-                    statisticsGatheringOnTheFlyService, deviceContext, /*MultipartType.OFPMPFLOW*/ multipartType) : emptyFuture;
-        }
+    private ListenableFuture<Boolean> collectFlowStatistics(final MultipartType multipartType) {
+        return devState.isFlowStatisticsAvailable() ? StatisticsGatheringUtils.gatherStatistics(
+                statisticsGatheringOnTheFlyService, deviceContext, /*MultipartType.OFPMPFLOW*/ multipartType) : emptyFuture;
+    }
 
-        private ListenableFuture<Boolean> collectTableStatistics ( final MultipartType multipartType){
-            return devState.isTableStatisticsAvailable() ? StatisticsGatheringUtils.gatherStatistics(
-                    statisticsGatheringService, deviceContext, /*MultipartType.OFPMPTABLE*/ multipartType) : emptyFuture;
-        }
+    private ListenableFuture<Boolean> collectTableStatistics(final MultipartType multipartType) {
+        return devState.isTableStatisticsAvailable() ? StatisticsGatheringUtils.gatherStatistics(
+                statisticsGatheringService, deviceContext, /*MultipartType.OFPMPTABLE*/ multipartType) : emptyFuture;
+    }
 
-        private ListenableFuture<Boolean> collectPortStatistics ( final MultipartType multipartType){
-            return devState.isPortStatisticsAvailable() ? StatisticsGatheringUtils.gatherStatistics(
-                    statisticsGatheringService, deviceContext, /*MultipartType.OFPMPPORTSTATS*/ multipartType) : emptyFuture;
-        }
+    private ListenableFuture<Boolean> collectPortStatistics(final MultipartType multipartType) {
+        return devState.isPortStatisticsAvailable() ? StatisticsGatheringUtils.gatherStatistics(
+                statisticsGatheringService, deviceContext, /*MultipartType.OFPMPPORTSTATS*/ multipartType) : emptyFuture;
+    }
 
-        private ListenableFuture<Boolean> collectQueueStatistics ( final MultipartType multipartType){
-            return devState.isQueueStatisticsAvailable() ? StatisticsGatheringUtils.gatherStatistics(
-                    statisticsGatheringService, deviceContext, /*MultipartType.OFPMPQUEUE*/ multipartType) : emptyFuture;
-        }
+    private ListenableFuture<Boolean> collectQueueStatistics(final MultipartType multipartType) {
+        return devState.isQueueStatisticsAvailable() ? StatisticsGatheringUtils.gatherStatistics(
+                statisticsGatheringService, deviceContext, /*MultipartType.OFPMPQUEUE*/ multipartType) : emptyFuture;
+    }
 
-        private ListenableFuture<Boolean> collectGroupDescStatistics ( final MultipartType multipartType){
-            return devState.isGroupAvailable() ? StatisticsGatheringUtils.gatherStatistics(
-                    statisticsGatheringService, deviceContext, /*MultipartType.OFPMPGROUPDESC*/ multipartType) : emptyFuture;
-        }
+    private ListenableFuture<Boolean> collectGroupDescStatistics(final MultipartType multipartType) {
+        return devState.isGroupAvailable() ? StatisticsGatheringUtils.gatherStatistics(
+                statisticsGatheringService, deviceContext, /*MultipartType.OFPMPGROUPDESC*/ multipartType) : emptyFuture;
+    }
 
-        private ListenableFuture<Boolean> collectGroupStatistics ( final MultipartType multipartType){
-            return devState.isGroupAvailable() ? StatisticsGatheringUtils.gatherStatistics(
-                    statisticsGatheringService, deviceContext, /*MultipartType.OFPMPGROUP*/ multipartType) : emptyFuture;
-        }
+    private ListenableFuture<Boolean> collectGroupStatistics(final MultipartType multipartType) {
+        return devState.isGroupAvailable() ? StatisticsGatheringUtils.gatherStatistics(
+                statisticsGatheringService, deviceContext, /*MultipartType.OFPMPGROUP*/ multipartType) : emptyFuture;
+    }
 
-        private ListenableFuture<Boolean> collectMeterConfigStatistics ( final MultipartType multipartType){
-            return devState.isMetersAvailable() ? StatisticsGatheringUtils.gatherStatistics(
-                    statisticsGatheringService, deviceContext, /*MultipartType.OFPMPMETERCONFIG*/ multipartType) : emptyFuture;
-        }
+    private ListenableFuture<Boolean> collectMeterConfigStatistics(final MultipartType multipartType) {
+        return devState.isMetersAvailable() ? StatisticsGatheringUtils.gatherStatistics(
+                statisticsGatheringService, deviceContext, /*MultipartType.OFPMPMETERCONFIG*/ multipartType) : emptyFuture;
+    }
 
-        private ListenableFuture<Boolean> collectMeterStatistics ( final MultipartType multipartType){
-            return devState.isMetersAvailable() ? StatisticsGatheringUtils.gatherStatistics(
-                    statisticsGatheringService, deviceContext, /*MultipartType.OFPMPMETER*/ multipartType) : emptyFuture;
-        }
+    private ListenableFuture<Boolean> collectMeterStatistics(final MultipartType multipartType) {
+        return devState.isMetersAvailable() ? StatisticsGatheringUtils.gatherStatistics(
+                statisticsGatheringService, deviceContext, /*MultipartType.OFPMPMETER*/ multipartType) : emptyFuture;
+    }
 
     @VisibleForTesting
-    protected void setStatisticsGatheringService(final StatisticsGatheringService statisticsGatheringService) {
+    void setStatisticsGatheringService(final StatisticsGatheringService statisticsGatheringService) {
         this.statisticsGatheringService = statisticsGatheringService;
     }
 
     @VisibleForTesting
-    protected void setStatisticsGatheringOnTheFlyService(final StatisticsGatheringOnTheFlyService
+    void setStatisticsGatheringOnTheFlyService(final StatisticsGatheringOnTheFlyService
                                                              statisticsGatheringOnTheFlyService) {
         this.statisticsGatheringOnTheFlyService = statisticsGatheringOnTheFlyService;
     }
index 4af98e00f3de72dc1713e0584f1bf6dd73f804d2..cc97c8fcc6bab1c55863c43ce6ab049126d1344b 100644 (file)
@@ -213,7 +213,7 @@ public final class StatisticsGatheringUtils {
         });
     }
 
-    private static void processMeterConfigStatsUpdated(final Iterable<MeterConfigStatsUpdated> data, final DeviceContext deviceContext) {
+    private static void processMeterConfigStatsUpdated(final Iterable<MeterConfigStatsUpdated> data, final DeviceContext deviceContext) throws Exception {
         final InstanceIdentifier<FlowCapableNode> fNodeIdent = assembleFlowCapableNodeInstanceIdentifier(deviceContext);
         deleteAllKnownMeters(deviceContext, fNodeIdent);
         for (final MeterConfigStatsUpdated meterConfigStatsUpdated : data) {
@@ -248,21 +248,25 @@ public final class StatisticsGatheringUtils {
 
     public static void writeFlowStatistics(final Iterable<FlowsStatisticsUpdate> data, final DeviceContext deviceContext) {
         final InstanceIdentifier<FlowCapableNode> fNodeIdent = assembleFlowCapableNodeInstanceIdentifier(deviceContext);
-        for (final FlowsStatisticsUpdate flowsStatistics : data) {
-            for (final FlowAndStatisticsMapList flowStat : flowsStatistics.getFlowAndStatisticsMapList()) {
-                final FlowBuilder flowBuilder = new FlowBuilder(flowStat);
-                flowBuilder.addAugmentation(FlowStatisticsData.class, refineFlowStatisticsAugmentation(flowStat).build());
-
-                final short tableId = flowStat.getTableId();
-                final FlowRegistryKey flowRegistryKey = FlowRegistryKeyFactory.create(flowBuilder.build());
-                final FlowId flowId = deviceContext.getDeviceFlowRegistry().storeIfNecessary(flowRegistryKey, tableId);
-
-                final FlowKey flowKey = new FlowKey(flowId);
-                flowBuilder.setKey(flowKey);
-                final TableKey tableKey = new TableKey(tableId);
-                final InstanceIdentifier<Flow> flowIdent = fNodeIdent.child(Table.class, tableKey).child(Flow.class, flowKey);
-                deviceContext.writeToTransaction(LogicalDatastoreType.OPERATIONAL, flowIdent, flowBuilder.build());
+        try {
+            for (final FlowsStatisticsUpdate flowsStatistics : data) {
+                for (final FlowAndStatisticsMapList flowStat : flowsStatistics.getFlowAndStatisticsMapList()) {
+                    final FlowBuilder flowBuilder = new FlowBuilder(flowStat);
+                    flowBuilder.addAugmentation(FlowStatisticsData.class, refineFlowStatisticsAugmentation(flowStat).build());
+
+                    final short tableId = flowStat.getTableId();
+                    final FlowRegistryKey flowRegistryKey = FlowRegistryKeyFactory.create(flowBuilder.build());
+                    final FlowId flowId = deviceContext.getDeviceFlowRegistry().storeIfNecessary(flowRegistryKey, tableId);
+
+                    final FlowKey flowKey = new FlowKey(flowId);
+                    flowBuilder.setKey(flowKey);
+                    final TableKey tableKey = new TableKey(tableId);
+                    final InstanceIdentifier<Flow> flowIdent = fNodeIdent.child(Table.class, tableKey).child(Flow.class, flowKey);
+                    deviceContext.writeToTransaction(LogicalDatastoreType.OPERATIONAL, flowIdent, flowBuilder.build());
+                }
             }
+        } catch (Exception e) {
+            LOG.warn("Not able to write to transaction: {}", e.getMessage());
         }
     }
 
@@ -320,7 +324,7 @@ public final class StatisticsGatheringUtils {
         return Futures.immediateFuture(null);
     }
 
-    private static void processQueueStatistics(final Iterable<QueueStatisticsUpdate> data, final DeviceContext deviceContext) {
+    private static void processQueueStatistics(final Iterable<QueueStatisticsUpdate> data, final DeviceContext deviceContext) throws Exception {
         // TODO: clean all queues of all node-connectors before writing up-to-date stats
         final InstanceIdentifier<Node> nodeIdent = deviceContext.getDeviceState().getNodeInstanceIdentifier();
         for (final QueueStatisticsUpdate queueStatisticsUpdate : data) {
@@ -348,7 +352,7 @@ public final class StatisticsGatheringUtils {
         deviceContext.submitTransaction();
     }
 
-    private static void processFlowTableStatistics(final Iterable<FlowTableStatisticsUpdate> data, final DeviceContext deviceContext) {
+    private static void processFlowTableStatistics(final Iterable<FlowTableStatisticsUpdate> data, final DeviceContext deviceContext) throws Exception {
         final InstanceIdentifier<FlowCapableNode> fNodeIdent = assembleFlowCapableNodeInstanceIdentifier(deviceContext);
         for (final FlowTableStatisticsUpdate flowTableStatisticsUpdate : data) {
 
@@ -362,7 +366,7 @@ public final class StatisticsGatheringUtils {
         deviceContext.submitTransaction();
     }
 
-    private static void processNodeConnectorStatistics(final Iterable<NodeConnectorStatisticsUpdate> data, final DeviceContext deviceContext) {
+    private static void processNodeConnectorStatistics(final Iterable<NodeConnectorStatisticsUpdate> data, final DeviceContext deviceContext) throws Exception {
         final InstanceIdentifier<Node> nodeIdent = deviceContext.getDeviceState().getNodeInstanceIdentifier();
         for (final NodeConnectorStatisticsUpdate nodeConnectorStatisticsUpdate : data) {
             for (final NodeConnectorStatisticsAndPortNumberMap nConnectPort : nodeConnectorStatisticsUpdate.getNodeConnectorStatisticsAndPortNumberMap()) {
@@ -380,7 +384,7 @@ public final class StatisticsGatheringUtils {
     }
 
     private static void processMetersStatistics(final Iterable<MeterStatisticsUpdated> data,
-                                                final DeviceContext deviceContext) {
+                                                final DeviceContext deviceContext) throws Exception {
         final InstanceIdentifier<FlowCapableNode> fNodeIdent = assembleFlowCapableNodeInstanceIdentifier(deviceContext);
         for (final MeterStatisticsUpdated meterStatisticsUpdated : data) {
             for (final MeterStats mStat : meterStatisticsUpdated.getMeterStats()) {
@@ -396,7 +400,7 @@ public final class StatisticsGatheringUtils {
         deviceContext.submitTransaction();
     }
 
-    private static void deleteAllKnownMeters(final DeviceContext deviceContext, final InstanceIdentifier<FlowCapableNode> fNodeIdent) {
+    private static void deleteAllKnownMeters(final DeviceContext deviceContext, final InstanceIdentifier<FlowCapableNode> fNodeIdent) throws Exception {
         for (final MeterId meterId : deviceContext.getDeviceMeterRegistry().getAllMeterIds()) {
             final InstanceIdentifier<Meter> meterIdent = fNodeIdent.child(Meter.class, new MeterKey(meterId));
             deviceContext.addDeleteToTxChain(LogicalDatastoreType.OPERATIONAL, meterIdent);
@@ -404,7 +408,7 @@ public final class StatisticsGatheringUtils {
         deviceContext.getDeviceMeterRegistry().removeMarked();
     }
 
-    private static void processGroupDescStats(final Iterable<GroupDescStatsUpdated> data, final DeviceContext deviceContext) {
+    private static void processGroupDescStats(final Iterable<GroupDescStatsUpdated> data, final DeviceContext deviceContext) throws Exception {
         final InstanceIdentifier<FlowCapableNode> fNodeIdent =
                 deviceContext.getDeviceState().getNodeInstanceIdentifier().augmentation(FlowCapableNode.class);
         deleteAllKnownGroups(deviceContext, fNodeIdent);
@@ -426,7 +430,7 @@ public final class StatisticsGatheringUtils {
         deviceContext.submitTransaction();
     }
 
-    private static void deleteAllKnownGroups(final DeviceContext deviceContext, final InstanceIdentifier<FlowCapableNode> fNodeIdent) {
+    private static void deleteAllKnownGroups(final DeviceContext deviceContext, final InstanceIdentifier<FlowCapableNode> fNodeIdent) throws Exception {
         for (final GroupId groupId : deviceContext.getDeviceGroupRegistry().getAllGroupIds()) {
             final InstanceIdentifier<Group> groupIdent = fNodeIdent.child(Group.class, new GroupKey(groupId));
             deviceContext.addDeleteToTxChain(LogicalDatastoreType.OPERATIONAL, groupIdent);
@@ -434,7 +438,7 @@ public final class StatisticsGatheringUtils {
         deviceContext.getDeviceGroupRegistry().removeMarked();
     }
 
-    private static void processGroupStatistics(final Iterable<GroupStatisticsUpdated> data, final DeviceContext deviceContext) {
+    private static void processGroupStatistics(final Iterable<GroupStatisticsUpdated> data, final DeviceContext deviceContext) throws Exception {
         final InstanceIdentifier<FlowCapableNode> fNodeIdent = assembleFlowCapableNodeInstanceIdentifier(deviceContext);
         for (final GroupStatisticsUpdated groupStatistics : data) {
             for (final GroupStats groupStats : groupStatistics.getGroupStats()) {
@@ -460,7 +464,7 @@ public final class StatisticsGatheringUtils {
      *
      * @param deviceContext txManager + node path keeper
      */
-    public static void markDeviceStateSnapshotStart(DeviceContext deviceContext) {
+    static void markDeviceStateSnapshotStart(final DeviceContext deviceContext) {
         final InstanceIdentifier<FlowCapableStatisticsGatheringStatus> statusPath = deviceContext.getDeviceState()
                 .getNodeInstanceIdentifier().augmentation(FlowCapableStatisticsGatheringStatus.class);
 
@@ -471,8 +475,12 @@ public final class StatisticsGatheringUtils {
                         .build())
                 .setSnapshotGatheringStatusEnd(null) // TODO: reconsider if really need to clean end mark here
                 .build();
+        try {
+            deviceContext.writeToTransaction(LogicalDatastoreType.OPERATIONAL, statusPath, gatheringStatus);
+        } catch (final Exception e) {
+            LOG.warn("Can't write to transaction: {}", e);
+        }
 
-        deviceContext.writeToTransaction(LogicalDatastoreType.OPERATIONAL, statusPath, gatheringStatus);
         deviceContext.submitTransaction();
     }
 
@@ -482,7 +490,7 @@ public final class StatisticsGatheringUtils {
      * @param deviceContext txManager + node path keeper
      * @param succeeded     outcome of currently finished gathering
      */
-    public static void markDeviceStateSnapshotEnd(DeviceContext deviceContext, final boolean succeeded) {
+    static void markDeviceStateSnapshotEnd(final DeviceContext deviceContext, final boolean succeeded) {
         final InstanceIdentifier<SnapshotGatheringStatusEnd> statusEndPath = deviceContext.getDeviceState()
                 .getNodeInstanceIdentifier().augmentation(FlowCapableStatisticsGatheringStatus.class)
                 .child(SnapshotGatheringStatusEnd.class);
@@ -492,8 +500,12 @@ public final class StatisticsGatheringUtils {
                 .setEnd(new DateAndTime(simpleDateFormat.format(new Date())))
                 .setSucceeded(succeeded)
                 .build();
+        try {
+            deviceContext.writeToTransaction(LogicalDatastoreType.OPERATIONAL, statusEndPath, gatheringStatus);
+        } catch (Exception e) {
+            LOG.warn("Can't write to transaction: {}", e);
+        }
 
-        deviceContext.writeToTransaction(LogicalDatastoreType.OPERATIONAL, statusEndPath, gatheringStatus);
         deviceContext.submitTransaction();
     }
 }
index dc0661cb739d33c820cee3cd2576e3673a85bc75..07e4b6df929c12f80a0b3e32fb8e780930cc75f6 100644 (file)
@@ -25,21 +25,24 @@ import com.google.common.collect.Iterators;
 import com.google.common.util.concurrent.FutureCallback;
 import com.google.common.util.concurrent.Futures;
 import com.google.common.util.concurrent.ListenableFuture;
-import io.netty.util.HashedWheelTimer;
 import io.netty.util.Timeout;
 import io.netty.util.TimerTask;
 import java.util.Iterator;
+import java.util.concurrent.CancellationException;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.ConcurrentMap;
 import java.util.concurrent.Future;
 import java.util.concurrent.Semaphore;
 import java.util.concurrent.TimeUnit;
 import javax.annotation.CheckForNull;
+import javax.annotation.Nonnull;
+
 import org.opendaylight.controller.sal.binding.api.BindingAwareBroker;
 import org.opendaylight.controller.sal.binding.api.RpcProviderRegistry;
 import org.opendaylight.openflowplugin.api.openflow.device.DeviceContext;
 import org.opendaylight.openflowplugin.api.openflow.device.handlers.DeviceInitializationPhaseHandler;
 import org.opendaylight.openflowplugin.api.openflow.device.handlers.DeviceTerminationPhaseHandler;
+import org.opendaylight.openflowplugin.api.openflow.lifecycle.LifecycleConductor;
 import org.opendaylight.openflowplugin.api.openflow.rpc.ItemLifeCycleSource;
 import org.opendaylight.openflowplugin.api.openflow.statistics.StatisticsContext;
 import org.opendaylight.openflowplugin.api.openflow.statistics.StatisticsManager;
@@ -56,9 +59,6 @@ import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-/**
- * Created by Martin Bobak &lt;mbobak@cisco.com&gt; on 1.4.2015.
- */
 public class StatisticsManagerImpl implements StatisticsManager, StatisticsManagerControlService {
 
     private static final Logger LOG = LoggerFactory.getLogger(StatisticsManagerImpl.class);
@@ -68,8 +68,6 @@ public class StatisticsManagerImpl implements StatisticsManager, StatisticsManag
     private DeviceInitializationPhaseHandler deviceInitPhaseHandler;
     private DeviceTerminationPhaseHandler deviceTerminPhaseHandler;
 
-    private HashedWheelTimer hashedWheelTimer;
-
     private final ConcurrentMap<NodeId, StatisticsContext> contexts = new ConcurrentHashMap<>();
 
     private static final long basicTimerDelay = 3000;
@@ -81,81 +79,40 @@ public class StatisticsManagerImpl implements StatisticsManager, StatisticsManag
     private boolean shuttingDownStatisticsPolling;
     private BindingAwareBroker.RpcRegistration<StatisticsManagerControlService> controlServiceRegistration;
 
+    private final LifecycleConductor conductor;
+
     @Override
     public void setDeviceInitializationPhaseHandler(final DeviceInitializationPhaseHandler handler) {
         deviceInitPhaseHandler = handler;
     }
 
     public StatisticsManagerImpl(@CheckForNull final RpcProviderRegistry rpcProviderRegistry,
-                                               final boolean shuttingDownStatisticsPolling) {
+                                 final boolean shuttingDownStatisticsPolling,
+                                 final LifecycleConductor lifecycleConductor) {
         Preconditions.checkArgument(rpcProviderRegistry != null);
         this.controlServiceRegistration = Preconditions.checkNotNull(rpcProviderRegistry.addRpcImplementation(
                 StatisticsManagerControlService.class, this));
         this.shuttingDownStatisticsPolling = shuttingDownStatisticsPolling;
+        this.conductor = lifecycleConductor;
     }
 
     @Override
-    public void onDeviceContextLevelUp(final DeviceContext deviceContext) throws Exception {
-        final NodeId nodeId = deviceContext.getDeviceState().getNodeId();
-        final OfpRole ofpRole = deviceContext.getDeviceState().getRole();
-        LOG.debug("Node:{}, deviceContext.getDeviceState().getRole():{}", nodeId, ofpRole);
-
-        if (null == hashedWheelTimer) {
-            LOG.trace("This is first device that delivered timer. Starting statistics polling immediately.");
-            hashedWheelTimer = deviceContext.getTimer();
-        }
-        final StatisticsContext statisticsContext = new StatisticsContextImpl(deviceContext, shuttingDownStatisticsPolling);
+    public void onDeviceContextLevelUp(final NodeId nodeId) throws Exception {
+
+        final DeviceContext deviceContext = Preconditions.checkNotNull(conductor.getDeviceContext(nodeId));
 
+        final StatisticsContext statisticsContext = new StatisticsContextImpl(nodeId, shuttingDownStatisticsPolling, conductor);
         Verify.verify(contexts.putIfAbsent(nodeId, statisticsContext) == null, "StatisticsCtx still not closed for Node {}", nodeId);
-        deviceContext.addDeviceContextClosedHandler(this);
 
         if (shuttingDownStatisticsPolling) {
-            LOG.info("Statistics is shutdown for node:{}", deviceContext.getDeviceState().getNodeId());
+            LOG.info("Statistics is shutdown for node:{}", nodeId);
         } else {
-            LOG.info("Schedule Statistics poll for node:{}", deviceContext.getDeviceState().getNodeId());
-            if (OfpRole.BECOMEMASTER.equals(ofpRole)) {
-                initialStatPollForMaster(statisticsContext, deviceContext);
-                /* we want to wait for initial statCollecting response */
-                return;
-            }
+            LOG.info("Schedule Statistics poll for node:{}", nodeId);
             scheduleNextPolling(deviceContext, statisticsContext, new TimeCounter());
         }
-        deviceContext.getDeviceState().setDeviceSynchronized(true);
-        deviceInitPhaseHandler.onDeviceContextLevelUp(deviceContext);
-    }
-
-    private void initialStatPollForMaster(final StatisticsContext statisticsContext, final DeviceContext deviceContext) {
-        final ListenableFuture<Boolean> weHaveDynamicData = statisticsContext.gatherDynamicData();
-        Futures.addCallback(weHaveDynamicData, new FutureCallback<Boolean>() {
-            @Override
-            public void onSuccess(final Boolean statisticsGathered) {
-                if (statisticsGathered) {
-                    //there are some statistics on device worth gathering
-                    final TimeCounter timeCounter = new TimeCounter();
-                    deviceContext.getDeviceState().setStatisticsPollingEnabledProp(true);
-                    scheduleNextPolling(deviceContext, statisticsContext, timeCounter);
-                    LOG.trace("Device dynamic info collecting done. Going to announce raise to next level.");
-                    try {
-                        deviceInitPhaseHandler.onDeviceContextLevelUp(deviceContext);
-                    } catch (final Exception e) {
-                        LOG.info("failed to complete levelUp on next handler for device {}", deviceContext.getDeviceState().getNodeId());
-                        deviceContext.shutdownConnection();
-                        return;
-                    }
-                    deviceContext.getDeviceState().setDeviceSynchronized(true);
-                } else {
-                    final String deviceAddress = deviceContext.getPrimaryConnectionContext().getConnectionAdapter().getRemoteAddress().toString();
-                    LOG.info("Statistics for device {} could not be gathered. Closing its device context.", deviceAddress);
-                    deviceContext.shutdownConnection();
-                }
-            }
 
-            @Override
-            public void onFailure(final Throwable throwable) {
-                LOG.warn("Statistics manager was not able to collect dynamic info for device.", deviceContext.getDeviceState().getNodeId(), throwable);
-                deviceContext.shutdownConnection();
-            }
-        });
+        deviceContext.getDeviceState().setDeviceSynchronized(true);
+        deviceInitPhaseHandler.onDeviceContextLevelUp(nodeId);
     }
 
     private void pollStatistics(final DeviceContext deviceContext,
@@ -171,12 +128,12 @@ public class StatisticsManagerImpl implements StatisticsManager, StatisticsManag
             scheduleNextPolling(deviceContext, statisticsContext, timeCounter);
             return;
         }
+
         if (!OfpRole.BECOMEMASTER.equals(deviceContext.getDeviceState().getRole())) {
             LOG.debug("Role is not Master so we don't want to poll any stat for device: {}", deviceContext.getDeviceState().getNodeId());
             scheduleNextPolling(deviceContext, statisticsContext, timeCounter);
             return;
         }
-
         LOG.debug("POLLING ALL STATS for device: {}", deviceContext.getDeviceState().getNodeId().getValue());
         timeCounter.markStart();
         final ListenableFuture<Boolean> deviceStatisticsCollectionFuture = statisticsContext.gatherDynamicData();
@@ -189,17 +146,22 @@ public class StatisticsManagerImpl implements StatisticsManager, StatisticsManag
             }
 
             @Override
-            public void onFailure(final Throwable throwable) {
+            public void onFailure(@Nonnull final Throwable throwable) {
                 timeCounter.addTimeMark();
-                LOG.info("Statistics gathering for single node was not successful: {}", throwable.getMessage());
-                LOG.debug("Statistics gathering for single node was not successful.. ", throwable);
+                LOG.warn("Statistics gathering for single node was not successful: {}", throwable.getMessage());
+                LOG.trace("Statistics gathering for single node was not successful.. ", throwable);
                 calculateTimerDelay(timeCounter);
-                scheduleNextPolling(deviceContext, statisticsContext, timeCounter);
+                if (throwable instanceof CancellationException) {
+                    /** This often happens when something wrong with akka or DS, so closing connection will help to restart device **/
+                    conductor.closeConnection(deviceContext.getDeviceState().getNodeId());
+                } else {
+                    scheduleNextPolling(deviceContext, statisticsContext, timeCounter);
+                }
             }
         });
 
-        final long averangeTime = TimeUnit.MILLISECONDS.toSeconds(timeCounter.getAverageTimeBetweenMarks());
-        final long STATS_TIMEOUT_SEC = averangeTime > 0 ? 3 * averangeTime : DEFAULT_STATS_TIMEOUT_SEC;
+        final long averageTime = TimeUnit.MILLISECONDS.toSeconds(timeCounter.getAverageTimeBetweenMarks());
+        final long STATS_TIMEOUT_SEC = averageTime > 0 ? 3 * averageTime : DEFAULT_STATS_TIMEOUT_SEC;
         final TimerTask timerTask = new TimerTask() {
 
             @Override
@@ -211,30 +173,26 @@ public class StatisticsManagerImpl implements StatisticsManager, StatisticsManag
                 }
             }
         };
-        deviceContext.getTimer().newTimeout(timerTask, STATS_TIMEOUT_SEC, TimeUnit.SECONDS);
+        conductor.newTimeout(timerTask, STATS_TIMEOUT_SEC, TimeUnit.SECONDS);
     }
 
     private void scheduleNextPolling(final DeviceContext deviceContext,
                                      final StatisticsContext statisticsContext,
                                      final TimeCounter timeCounter) {
-        if (null != hashedWheelTimer) {
-            LOG.debug("SCHEDULING NEXT STATS POLLING for device: {}", deviceContext.getDeviceState().getNodeId().getValue());
-            if (!shuttingDownStatisticsPolling) {
-                final Timeout pollTimeout = hashedWheelTimer.newTimeout(new TimerTask() {
-                    @Override
-                    public void run(final Timeout timeout) throws Exception {
-                        pollStatistics(deviceContext, statisticsContext, timeCounter);
-                    }
-                }, currentTimerDelay, TimeUnit.MILLISECONDS);
-                statisticsContext.setPollTimeout(pollTimeout);
-            }
-        } else {
-            LOG.debug("#!NOT SCHEDULING NEXT STATS POLLING for device: {}", deviceContext.getDeviceState().getNodeId().getValue());
+        LOG.debug("SCHEDULING NEXT STATS POLLING for device: {}", deviceContext.getDeviceState().getNodeId().getValue());
+        if (!shuttingDownStatisticsPolling) {
+            final Timeout pollTimeout = conductor.newTimeout(new TimerTask() {
+                @Override
+                public void run(final Timeout timeout) throws Exception {
+                    pollStatistics(deviceContext, statisticsContext, timeCounter);
+                }
+            }, currentTimerDelay, TimeUnit.MILLISECONDS);
+            statisticsContext.setPollTimeout(pollTimeout);
         }
     }
 
     @VisibleForTesting
-    protected void calculateTimerDelay(final TimeCounter timeCounter) {
+    void calculateTimerDelay(final TimeCounter timeCounter) {
         final long averageStatisticsGatheringTime = timeCounter.getAverageTimeBetweenMarks();
         if (averageStatisticsGatheringTime > currentTimerDelay) {
             currentTimerDelay *= 2;
@@ -251,7 +209,7 @@ public class StatisticsManagerImpl implements StatisticsManager, StatisticsManag
     }
 
     @VisibleForTesting
-    protected static long getCurrentTimerDelay() {
+    static long getCurrentTimerDelay() {
         return currentTimerDelay;
     }
 
index 4311882833638e3e373d06f6d7965e6bf7f4b454..00ed2fb06af5d760a3978b1328250ec8b2fb64cb 100644 (file)
@@ -431,7 +431,7 @@ public class DeviceInitializationUtils {
 
         final OutboundQueue queue = deviceContext.getPrimaryConnectionContext().getOutboundQueueProvider();
 
-        final Long reserved = deviceContext.reservedXidForDeviceMessage();
+        final Long reserved = deviceContext.reserveXidForDeviceMessage();
         final RequestContext<List<MultipartReply>> requestContext = new AbstractRequestContext<List<MultipartReply>>(
                 reserved) {
             @Override
index af48f96fdf42d6a028d103b0eb13892cfa49b451..58e85ca002a09479ca5771ae4b9c6e0ee13a2ed9 100644 (file)
@@ -25,9 +25,6 @@ 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;
@@ -59,6 +56,7 @@ import org.opendaylight.openflowplugin.api.openflow.device.RequestContext;
 import org.opendaylight.openflowplugin.api.openflow.device.TranslatorLibrary;
 import org.opendaylight.openflowplugin.api.openflow.device.Xid;
 import org.opendaylight.openflowplugin.api.openflow.device.handlers.DeviceTerminationPhaseHandler;
+import org.opendaylight.openflowplugin.api.openflow.lifecycle.LifecycleConductor;
 import org.opendaylight.openflowplugin.api.openflow.md.core.TranslatorKey;
 import org.opendaylight.openflowplugin.api.openflow.registry.flow.DeviceFlowRegistry;
 import org.opendaylight.openflowplugin.api.openflow.registry.flow.FlowDescriptor;
@@ -159,6 +157,8 @@ public class DeviceContextImplTest {
     MessageTranslator messageTranslatorFlowCapableNodeConnector;
     @Mock
     private MessageTranslator<Object, Object> messageTranslatorFlowRemoved;
+    @Mock
+    private LifecycleConductor lifecycleConductor;
 
     private InOrder inOrderDevState;
 
@@ -208,7 +208,7 @@ public class DeviceContextImplTest {
                 org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.FlowRemoved.class.getName()))))
                 .thenReturn(messageTranslatorFlowRemoved);
 
-        deviceContext = new DeviceContextImpl(connectionContext, deviceState, dataBroker, timer, messageIntelligenceAgency, outboundQueueProvider, translatorLibrary, false);
+        deviceContext = new DeviceContextImpl(connectionContext, deviceState, dataBroker, messageIntelligenceAgency, outboundQueueProvider, translatorLibrary, false);
 
         xid = new Xid(atomicLong.incrementAndGet());
         xidMulti = new Xid(atomicLong.incrementAndGet());
@@ -216,17 +216,17 @@ public class DeviceContextImplTest {
 
     @Test(expected = NullPointerException.class)
     public void testDeviceContextImplConstructorNullDataBroker() throws Exception {
-        new DeviceContextImpl(connectionContext, deviceState, null, timer, messageIntelligenceAgency, outboundQueueProvider, translatorLibrary, false).close();
+        new DeviceContextImpl(connectionContext, deviceState, null, messageIntelligenceAgency, outboundQueueProvider, translatorLibrary, false).close();
     }
 
     @Test(expected = NullPointerException.class)
     public void testDeviceContextImplConstructorNullDeviceState() throws Exception {
-        new DeviceContextImpl(connectionContext, null, dataBroker, timer, messageIntelligenceAgency, outboundQueueProvider, translatorLibrary, false).close();
+        new DeviceContextImpl(connectionContext, null, dataBroker, messageIntelligenceAgency, outboundQueueProvider, translatorLibrary, false).close();
     }
 
     @Test(expected = NullPointerException.class)
     public void testDeviceContextImplConstructorNullTimer() throws Exception {
-        new DeviceContextImpl(null, deviceState, dataBroker, null, messageIntelligenceAgency, outboundQueueProvider, translatorLibrary, false).close();
+        new DeviceContextImpl(null, deviceState, dataBroker, messageIntelligenceAgency, outboundQueueProvider, translatorLibrary, false).close();
     }
 
     @Test
@@ -256,7 +256,7 @@ public class DeviceContextImplTest {
 
     @Test
     public void testGetReservedXid() {
-        deviceContext.reservedXidForDeviceMessage();
+        deviceContext.reserveXidForDeviceMessage();
         verify(outboundQueueProvider).reserveEntry();
     }
 
@@ -376,12 +376,6 @@ public class DeviceContextImplTest {
         assertEquals(translatorLibrary, pickedTranslatorLibrary);
     }
 
-    @Test
-    public void testGetTimer() {
-        final HashedWheelTimer pickedTimer = deviceContext.getTimer();
-        assertEquals(timer, pickedTimer);
-    }
-
     @Test
     public void testShutdownConnection() {
         final ConnectionAdapter mockedConnectionAdapter = mock(ConnectionAdapter.class);
@@ -395,7 +389,6 @@ public class DeviceContextImplTest {
         final ConnectionContext mockedAuxiliaryConnectionContext = prepareConnectionContext();
         deviceContext.addAuxiliaryConnectionContext(mockedAuxiliaryConnectionContext);
         final DeviceTerminationPhaseHandler mockedDeviceContextClosedHandler = mock(DeviceTerminationPhaseHandler.class);
-        deviceContext.addDeviceContextClosedHandler(mockedDeviceContextClosedHandler);
         when(deviceState.isValid()).thenReturn(true);
         deviceContext.shutdownConnection();
         verify(connectionContext).closeConnection(true);
@@ -497,7 +490,6 @@ public class DeviceContextImplTest {
     @Test
     public void testOnDeviceDisconnected() throws Exception {
         final DeviceTerminationPhaseHandler deviceContextClosedHandler = mock(DeviceTerminationPhaseHandler.class);
-        deviceContext.addDeviceContextClosedHandler(deviceContextClosedHandler);
 
 //        Mockito.verify(deviceState).setValid(false);
 //        Mockito.verify(deviceContextClosedHandler).onDeviceContextClosed(deviceContext);
index 18140ac257ab256364ab4e0589a7289d5378c6c6..29c111e12ccd995f982603b68b2352694351b866 100644 (file)
@@ -52,8 +52,10 @@ import org.opendaylight.openflowplugin.api.openflow.device.MessageTranslator;
 import org.opendaylight.openflowplugin.api.openflow.device.TranslatorLibrary;
 import org.opendaylight.openflowplugin.api.openflow.device.handlers.DeviceInitializationPhaseHandler;
 import org.opendaylight.openflowplugin.api.openflow.device.handlers.DeviceTerminationPhaseHandler;
+import org.opendaylight.openflowplugin.api.openflow.lifecycle.LifecycleConductor;
 import org.opendaylight.openflowplugin.api.openflow.md.core.TranslatorKey;
 import org.opendaylight.openflowplugin.api.openflow.statistics.ofpspecific.MessageIntelligenceAgency;
+import org.opendaylight.openflowplugin.impl.LifecycleConductorImpl;
 import org.opendaylight.openflowplugin.openflow.md.util.OpenflowPortsUtil;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
@@ -148,8 +150,9 @@ public class DeviceManagerImplTest {
         when(mockedWriteTransaction.submit()).thenReturn(mockedFuture);
 
         final MessageIntelligenceAgency mockedMessageIntelligenceAgency = mock(MessageIntelligenceAgency.class);
-        final DeviceManagerImpl deviceManager = new DeviceManagerImpl(mockedDataBroker, mockedMessageIntelligenceAgency,
-                TEST_VALUE_GLOBAL_NOTIFICATION_QUOTA, false, barrierIntervalNanos, barrierCountLimit);
+        final LifecycleConductor lifecycleConductor = new LifecycleConductorImpl(mockedMessageIntelligenceAgency);
+        final DeviceManagerImpl deviceManager = new DeviceManagerImpl(mockedDataBroker,
+                TEST_VALUE_GLOBAL_NOTIFICATION_QUOTA, false, barrierIntervalNanos, barrierCountLimit, lifecycleConductor);
 
         deviceManager.setDeviceInitializationPhaseHandler(deviceInitPhaseHandler);
         deviceManager.setDeviceTerminationPhaseHandler(deviceTerminationPhaseHandler);
@@ -162,12 +165,13 @@ public class DeviceManagerImplTest {
         final DeviceState mockedDeviceState = mock(DeviceState.class);
         when(mockedDeviceContext.getDeviceState()).thenReturn(mockedDeviceState);
         when(mockedDeviceState.getRole()).thenReturn(OfpRole.BECOMEMASTER);
+        when(mockedDeviceState.getNodeId()).thenReturn(mockedNodeId);
 
         if (withException) {
             doThrow(new IllegalStateException("dummy")).when(mockedDeviceContext).initialSubmitTransaction();
         }
-
-        deviceManager.onDeviceContextLevelUp(mockedDeviceContext);
+        deviceManager.addDeviceContextToMap(mockedNodeId, mockedDeviceContext);
+        deviceManager.onDeviceContextLevelUp(mockedDeviceContext.getDeviceState().getNodeId());
         if (withException) {
             verify(mockedDeviceContext).close();
         } else {
@@ -190,7 +194,7 @@ public class DeviceManagerImplTest {
         order.verify(mockConnectionContext).setOutboundQueueHandleRegistration(
                 Mockito.<OutboundQueueHandlerRegistration<OutboundQueueProvider>>any());
         order.verify(mockConnectionContext).getNodeId();
-        Mockito.verify(deviceInitPhaseHandler).onDeviceContextLevelUp(Matchers.<DeviceContext>any());
+        Mockito.verify(deviceInitPhaseHandler).onDeviceContextLevelUp(Matchers.<NodeId>any());
     }
 
     @Test
@@ -215,7 +219,7 @@ public class DeviceManagerImplTest {
         order.verify(mockConnectionContext).setOutboundQueueHandleRegistration(
                 Mockito.<OutboundQueueHandlerRegistration<OutboundQueueProvider>>any());
         order.verify(mockConnectionContext).getNodeId();
-        Mockito.verify(deviceInitPhaseHandler).onDeviceContextLevelUp(Matchers.<DeviceContext>any());
+        Mockito.verify(deviceInitPhaseHandler).onDeviceContextLevelUp(Matchers.<NodeId>any());
     }
 
     protected ConnectionContext buildMockConnectionContext(final short ofpVersion) {
index bc0e0f4c0b0ef91c8b8455347a1aa4074b3a51e6..e88ce24a3e52378dc3d3d3f61ca826bcc726ff35 100644 (file)
  */
 package org.opendaylight.openflowplugin.impl.role;
 
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-import com.google.common.util.concurrent.Futures;
-import com.google.common.util.concurrent.ListenableFuture;
-import com.google.common.util.concurrent.SettableFuture;
-import java.util.concurrent.ExecutionException;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.TimeoutException;
+
+import org.junit.Assert;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
-import org.mockito.ArgumentMatcher;
-import org.mockito.Matchers;
 import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.invocation.InvocationOnMock;
 import org.mockito.runners.MockitoJUnitRunner;
-import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.mockito.stubbing.Answer;
 import org.opendaylight.controller.md.sal.common.api.clustering.CandidateAlreadyRegisteredException;
 import org.opendaylight.controller.md.sal.common.api.clustering.Entity;
+import org.opendaylight.controller.md.sal.common.api.clustering.EntityOwnershipCandidateRegistration;
 import org.opendaylight.controller.md.sal.common.api.clustering.EntityOwnershipService;
-import org.opendaylight.controller.sal.binding.api.RpcProviderRegistry;
-import org.opendaylight.openflowplugin.api.OFConstants;
-import org.opendaylight.openflowplugin.api.openflow.connection.ConnectionContext;
-import org.opendaylight.openflowplugin.api.openflow.device.DeviceContext;
-import org.opendaylight.openflowplugin.api.openflow.device.DeviceState;
+import org.opendaylight.openflowplugin.api.openflow.lifecycle.LifecycleConductor;
+import org.opendaylight.openflowplugin.api.openflow.role.RoleContext;
 import org.opendaylight.openflowplugin.api.openflow.role.RoleManager;
-import org.opendaylight.openflowplugin.api.openflow.statistics.ofpspecific.MessageSpy;
-import org.opendaylight.openflowplugin.impl.util.DeviceStateUtil;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeRef;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.NodeKey;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.FeaturesReply;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.GetFeaturesOutput;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.role.service.rev150727.OfpRole;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.role.service.rev150727.SalRoleService;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.role.service.rev150727.SetRoleInput;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.role.service.rev150727.SetRoleOutput;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.role.service.rev150727.SetRoleOutputBuilder;
-import org.opendaylight.yangtools.yang.binding.KeyedInstanceIdentifier;
-import org.opendaylight.yangtools.yang.common.RpcResult;
-import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 /**
- * Created by kramesha on 9/1/15.
+ * @author Jozef Bacigal
+ * Date: 4/19/16
+ * Time: 12:56
  */
 @RunWith(MockitoJUnitRunner.class)
 public class RoleContextImplTest {
 
-    public static final int FUTURE_SAFETY_TIMEOUT = 5;
-    @Mock
-    private EntityOwnershipService entityOwnershipService;
-
-    @Mock
-    private DataBroker dataBroker;
-
-    @Mock
-    private RpcProviderRegistry rpcProviderRegistry;
-
-    @Mock
-    private DeviceContext deviceContext;
-
-    @Mock
-    private ConnectionContext connectionContext;
+    private static final Logger LOG = LoggerFactory.getLogger(RoleContextImpl.class);
 
     @Mock
-    private DeviceState deviceState;
+    private EntityOwnershipService entityOwnershipService;
 
     @Mock
-    private SalRoleService salRoleService;
+    private EntityOwnershipCandidateRegistration entityOwnershipCandidateRegistration;
 
     @Mock
-    private GetFeaturesOutput getFeaturesOutput;
-
-    @Mock
-    private FeaturesReply featuresReply;
-    @Mock
-    private MessageSpy mockedMessageSpy;
+    private LifecycleConductor conductor;
 
     private final NodeId nodeId = NodeId.getDefaultInstance("openflow:1");
-    private final KeyedInstanceIdentifier<Node, NodeKey> instanceIdentifier = DeviceStateUtil.createNodeInstanceIdentifier(nodeId);
     private final Entity entity = new Entity(RoleManager.ENTITY_TYPE, nodeId.getValue());
     private final Entity txEntity = new Entity(RoleManager.TX_ENTITY_TYPE, nodeId.getValue());
-    private RoleContextImpl roleContext;
+    private RoleContext roleContext;
 
     @Before
     public void setup() throws CandidateAlreadyRegisteredException {
-        when(deviceContext.getPrimaryConnectionContext()).thenReturn(connectionContext);
-        when(deviceContext.getDeviceState()).thenReturn(deviceState);
-        when(deviceContext.getMessageSpy()).thenReturn(mockedMessageSpy);
-        when(connectionContext.getNodeId()).thenReturn(nodeId);
-        when(deviceState.getNodeInstanceIdentifier()).thenReturn(instanceIdentifier);
-        when(deviceState.getNodeId()).thenReturn(nodeId);
-        when(rpcProviderRegistry.getRpcService(SalRoleService.class)).thenReturn(salRoleService);
-        when(deviceState.getFeatures()).thenReturn(getFeaturesOutput);
-        when(getFeaturesOutput.getVersion()).thenReturn(OFConstants.OFP_VERSION_1_0);
-        when(deviceContext.getPrimaryConnectionContext().getFeatures()).thenReturn(featuresReply);
-        when(deviceContext.getPrimaryConnectionContext().getConnectionState()).thenReturn(ConnectionContext.CONNECTION_STATE.WORKING);
-        when(deviceContext.onClusterRoleChange(Matchers.<OfpRole>any(), Matchers.<OfpRole>any()))
-            .thenReturn(Futures.immediateFuture((Void) null));
-
-        roleContext = new RoleContextImpl(deviceContext, entityOwnershipService, entity, txEntity);
-        roleContext.initializationRoleContext();
+        roleContext = new RoleContextImpl(nodeId, entityOwnershipService, entity, txEntity, conductor);
+        Mockito.when(entityOwnershipService.registerCandidate(entity)).thenReturn(entityOwnershipCandidateRegistration);
+        Mockito.when(entityOwnershipService.registerCandidate(txEntity)).thenReturn(entityOwnershipCandidateRegistration);
     }
 
-    @Test
-    public void testOnRoleChangedStartingMaster() throws InterruptedException, ExecutionException, TimeoutException {
-        final OfpRole oldRole = OfpRole.BECOMESLAVE;
-        final OfpRole newRole = OfpRole.BECOMEMASTER;
+//  @Test
+//  Run this test only if demanded because it takes 15s to run
+    public void testInitializationThreads() throws Exception {
+
+        /*Setting answer which will hold the answer for 5s*/
+        Mockito.when(entityOwnershipService.registerCandidate(entity)).thenAnswer(new Answer<EntityOwnershipService>() {
+            @Override
+            public EntityOwnershipService answer(final InvocationOnMock invocationOnMock) throws Throwable {
+                LOG.info("Sleeping this thread for 14s");
+                Thread.sleep(14000L);
+                return null;
+            }
+        });
 
-        final SettableFuture<RpcResult<SetRoleOutput>> future = SettableFuture.create();
-        future.set(RpcResultBuilder.<SetRoleOutput>success().build());
-        when(salRoleService.setRole(Matchers.argThat(new SetRoleInputMatcher(newRole, instanceIdentifier))))
-                .thenReturn(future);
+        Thread t1 = new Thread(new Runnable() {
+            @Override
+            public void run() {
+                LOG.info("Starting thread 1");
+                Assert.assertTrue(roleContext.initialization());
+            }
+        });
 
-        roleContext.setSalRoleService(salRoleService);
+        Thread t2 = new Thread(new Runnable() {
+            @Override
+            public void run() {
+                LOG.info("Starting thread 2");
+                Assert.assertFalse(roleContext.initialization());
+            }
+        });
 
-        final ListenableFuture<Void> onRoleChanged = roleContext.onRoleChanged(oldRole, newRole);
-        onRoleChanged.get(FUTURE_SAFETY_TIMEOUT, TimeUnit.SECONDS);
+        t1.start();
+        LOG.info("Sleeping main thread for 1s to prevent race condition.");
+        Thread.sleep(1000L);
+        t2.start();
+
+        while (t2.isAlive()) {
+            //Waiting
+        }
 
-        verify(deviceContext).onClusterRoleChange(oldRole, newRole);
     }
 
     @Test
-    public void testOnRoleChangedStartingSlave() throws InterruptedException, ExecutionException, TimeoutException {
-        final OfpRole oldRole = OfpRole.BECOMEMASTER;
-        final OfpRole newRole = OfpRole.BECOMESLAVE;
-
-        final SettableFuture<RpcResult<SetRoleOutput>> future = SettableFuture.create();
-        future.set(RpcResultBuilder.<SetRoleOutput>success().build());
-        when(salRoleService.setRole(Matchers.argThat(new SetRoleInputMatcher(newRole, instanceIdentifier))))
-                .thenReturn(future);
-
-        roleContext.setSalRoleService(salRoleService);
-
-        final ListenableFuture<Void> onRoleChanged = roleContext.onRoleChanged(oldRole, newRole);
-        onRoleChanged.get(5, TimeUnit.SECONDS);
-
-        verify(deviceContext).onClusterRoleChange(oldRole, newRole);
+    public void testTermination() throws Exception {
+        roleContext.registerCandidate(entity);
+        roleContext.registerCandidate(txEntity);
+        Assert.assertTrue(roleContext.isMainCandidateRegistered());
+        Assert.assertTrue(roleContext.isTxCandidateRegistered());
+        roleContext.unregisterAllCandidates();
+        Assert.assertFalse(roleContext.isMainCandidateRegistered());
     }
 
     @Test
-    public void testOnRoleChangedWorkingMaster() throws InterruptedException, ExecutionException, TimeoutException {
-        final OfpRole oldRole = OfpRole.BECOMESLAVE;
-        final OfpRole newRole = OfpRole.BECOMEMASTER;
-
-        final ListenableFuture<RpcResult<SetRoleOutput>> future =
-                RpcResultBuilder.success(new SetRoleOutputBuilder().build()).buildFuture();
-        when(salRoleService.setRole(Matchers.argThat(new SetRoleInputMatcher(newRole, instanceIdentifier))))
-                .thenReturn(future);
-
-        roleContext.setSalRoleService(salRoleService);
+    public void testCreateRequestContext() throws Exception {
 
-        final ListenableFuture<Void> onRoleChanged = roleContext.onRoleChanged(oldRole, newRole);
-        onRoleChanged.get(5, TimeUnit.SECONDS);
+    }
 
-        verify(deviceContext).onClusterRoleChange(oldRole, newRole);
+    @Test(expected = NullPointerException.class)
+    public void testSetSalRoleService() throws Exception {
+        roleContext.setSalRoleService(null);
     }
 
     @Test
-    public void testOnRoleChangedWorkingSlave() throws InterruptedException, ExecutionException, TimeoutException {
-        final OfpRole oldRole = OfpRole.BECOMEMASTER;
-        final OfpRole newRole = OfpRole.BECOMESLAVE;
-
-        final SettableFuture<RpcResult<SetRoleOutput>> future = SettableFuture.create();
-        future.set(RpcResultBuilder.<SetRoleOutput>success().build());
-        when(salRoleService.setRole(Matchers.argThat(new SetRoleInputMatcher(newRole, instanceIdentifier))))
-                .thenReturn(future);
-
-        roleContext.setSalRoleService(salRoleService);
-
-        final ListenableFuture<Void> onRoleChanged = roleContext.onRoleChanged(oldRole, newRole);
-        onRoleChanged.get(5, TimeUnit.SECONDS);
-
-        verify(deviceContext).onClusterRoleChange(oldRole, newRole);
+    public void testGetEntity() throws Exception {
+        Assert.assertTrue(roleContext.getEntity().equals(entity));
     }
 
-    private class SetRoleInputMatcher extends ArgumentMatcher<SetRoleInput> {
-
-        private final OfpRole ofpRole;
-        private final NodeRef nodeRef;
-
-        public SetRoleInputMatcher(final OfpRole ofpRole, final KeyedInstanceIdentifier<Node, NodeKey> instanceIdentifier) {
-            this.ofpRole = ofpRole;
-            nodeRef = new NodeRef(instanceIdentifier);
+    @Test
+    public void testGetTxEntity() throws Exception {
+        Assert.assertTrue(roleContext.getTxEntity().equals(txEntity));
+    }
 
-        }
+    @Test
+    public void testGetNodeId() throws Exception {
+        Assert.assertTrue(roleContext.getNodeId().equals(nodeId));
+    }
 
-        @Override
-        public boolean matches(final Object o) {
-            final SetRoleInput input = (SetRoleInput) o;
-            if (input.getControllerRole() == ofpRole &&
-                    input.getNode().equals(nodeRef)) {
-                return true;
-            }
-            return false;
-        }
+    @Test
+    public void testIsMaster() throws Exception {
+        Assert.assertTrue(roleContext.initialization());
+        Assert.assertFalse(roleContext.isMaster());
+        Assert.assertTrue(roleContext.registerCandidate(txEntity));
+        Assert.assertTrue(roleContext.isMaster());
+        Assert.assertTrue(roleContext.unregisterCandidate(entity));
+        Assert.assertFalse(roleContext.isMaster());
     }
 }
diff --git a/openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/role/RoleManagerImplTest.java b/openflowplugin-impl/src/test/java/org/opendaylight/openflowplugin/impl/role/RoleManagerImplTest.java
new file mode 100644 (file)
index 0000000..bba0245
--- /dev/null
@@ -0,0 +1,243 @@
+/*
+ * Copyright (c) 2016 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.openflowplugin.impl.role;
+
+
+import java.math.BigInteger;
+
+import com.google.common.base.VerifyException;
+import com.google.common.util.concurrent.CheckedFuture;
+import com.google.common.util.concurrent.Futures;
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.InOrder;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.runners.MockitoJUnitRunner;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
+import org.opendaylight.controller.md.sal.common.api.clustering.Entity;
+import org.opendaylight.controller.md.sal.common.api.clustering.EntityOwnershipCandidateRegistration;
+import org.opendaylight.controller.md.sal.common.api.clustering.EntityOwnershipChange;
+import org.opendaylight.controller.md.sal.common.api.clustering.EntityOwnershipListener;
+import org.opendaylight.controller.md.sal.common.api.clustering.EntityOwnershipListenerRegistration;
+import org.opendaylight.controller.md.sal.common.api.clustering.EntityOwnershipService;
+import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
+import org.opendaylight.openflowplugin.api.OFConstants;
+import org.opendaylight.openflowplugin.api.openflow.connection.ConnectionContext;
+import org.opendaylight.openflowplugin.api.openflow.device.DeviceContext;
+import org.opendaylight.openflowplugin.api.openflow.device.DeviceManager;
+import org.opendaylight.openflowplugin.api.openflow.device.handlers.DeviceInitializationPhaseHandler;
+import org.opendaylight.openflowplugin.api.openflow.device.handlers.DeviceTerminationPhaseHandler;
+import org.opendaylight.openflowplugin.api.openflow.lifecycle.LifecycleConductor;
+import org.opendaylight.openflowplugin.api.openflow.lifecycle.RoleChangeListener;
+import org.opendaylight.openflowplugin.api.openflow.role.RoleContext;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.FeaturesReply;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.role.service.rev150727.OfpRole;
+
+/**
+ * Created by Jozef Bacigal
+ * Date: 19.4.2016.
+ * Time: 13:08
+ */
+@RunWith(MockitoJUnitRunner.class)
+public class RoleManagerImplTest {
+
+    @Mock
+    EntityOwnershipService entityOwnershipService;
+
+    @Mock
+    DataBroker dataBroker;
+
+    @Mock
+    DeviceContext deviceContext;
+
+    @Mock
+    DeviceManager deviceManager;
+
+    @Mock
+    EntityOwnershipListener entityOwnershipListener;
+
+    @Mock
+    EntityOwnershipListenerRegistration entityOwnershipListenerRegistration;
+
+    @Mock
+    EntityOwnershipCandidateRegistration entityOwnershipCandidateRegistration;
+
+    @Mock
+    ConnectionContext connectionContext;
+
+    @Mock
+    FeaturesReply featuresReply;
+
+    @Mock
+    DeviceInitializationPhaseHandler deviceInitializationPhaseHandler;
+
+    @Mock
+    DeviceTerminationPhaseHandler deviceTerminationPhaseHandler;
+
+    @Mock
+    WriteTransaction writeTransaction;
+
+    @Mock
+    LifecycleConductor conductor;
+
+    private RoleManagerImpl roleManager;
+    private RoleManagerImpl roleManagerSpy;
+    private RoleContext roleContextSpy;
+    private final NodeId nodeId = NodeId.getDefaultInstance("openflow:1");
+
+    private final EntityOwnershipChange masterEntity = new EntityOwnershipChange(RoleManagerImpl.makeEntity(nodeId), false, true, true);
+    private final EntityOwnershipChange masterTxEntity = new EntityOwnershipChange(RoleManagerImpl.makeTxEntity(nodeId), false, true, true);
+    private final EntityOwnershipChange slaveEntity = new EntityOwnershipChange(RoleManagerImpl.makeEntity(nodeId), true, false, true);
+    private final EntityOwnershipChange slaveTxEntityLast = new EntityOwnershipChange(RoleManagerImpl.makeTxEntity(nodeId), true, false, false);
+
+    private InOrder inOrder;
+
+    @Before
+    public void setUp() throws Exception {
+        CheckedFuture<Void, TransactionCommitFailedException> future = Futures.immediateCheckedFuture(null);
+        Mockito.when(entityOwnershipService.registerListener(Mockito.anyString(), Mockito.any(EntityOwnershipListener.class))).thenReturn(entityOwnershipListenerRegistration);
+        Mockito.when(entityOwnershipService.registerCandidate(Mockito.any(Entity.class))).thenReturn(entityOwnershipCandidateRegistration);
+        Mockito.when(deviceContext.getPrimaryConnectionContext()).thenReturn(connectionContext);
+        Mockito.when(connectionContext.getFeatures()).thenReturn(featuresReply);
+        Mockito.when(connectionContext.getNodeId()).thenReturn(nodeId);
+        Mockito.when(connectionContext.getConnectionState()).thenReturn(ConnectionContext.CONNECTION_STATE.WORKING);
+        Mockito.when(featuresReply.getDatapathId()).thenReturn(new BigInteger("1"));
+        Mockito.when(featuresReply.getVersion()).thenReturn(OFConstants.OFP_VERSION_1_3);
+        Mockito.doNothing().when(deviceInitializationPhaseHandler).onDeviceContextLevelUp(Mockito.<NodeId>any());
+        Mockito.doNothing().when(deviceTerminationPhaseHandler).onDeviceContextLevelDown(Mockito.<DeviceContext>any());
+        Mockito.when(dataBroker.newWriteOnlyTransaction()).thenReturn(writeTransaction);
+        Mockito.when(writeTransaction.submit()).thenReturn(future);
+        Mockito.when(deviceManager.getDeviceContextFromNodeId(Mockito.<NodeId>any())).thenReturn(deviceContext);
+        roleManager = new RoleManagerImpl(entityOwnershipService, dataBroker, conductor);
+        roleManager.setDeviceInitializationPhaseHandler(deviceInitializationPhaseHandler);
+        roleManager.setDeviceTerminationPhaseHandler(deviceTerminationPhaseHandler);
+        Mockito.when(conductor.getDeviceContext(Mockito.<NodeId>any())).thenReturn(deviceContext);
+        roleManagerSpy = Mockito.spy(roleManager);
+        Mockito.doNothing().when(roleManagerSpy).makeDeviceRoleChange(Mockito.<OfpRole>any(), Mockito.<RoleContext>any(), Mockito.anyBoolean());
+        roleManagerSpy.onDeviceContextLevelUp(nodeId);
+        roleContextSpy = Mockito.spy(roleManager.getRoleContext(nodeId));
+        inOrder = Mockito.inOrder(entityOwnershipListenerRegistration, roleManagerSpy, roleContextSpy);
+    }
+
+    @After
+    public void tearDown() throws Exception {
+    }
+
+    @Test(expected = VerifyException.class)
+    public void testOnDeviceContextLevelUp() throws Exception {
+        roleManagerSpy.onDeviceContextLevelUp(nodeId);
+        inOrder.verify(roleManagerSpy).onDeviceContextLevelUp(nodeId);
+        inOrder.verifyNoMoreInteractions();
+    }
+
+    @Test
+    public void testCloseMaster() throws Exception {
+        roleManagerSpy.ownershipChanged(masterEntity);
+        roleManagerSpy.ownershipChanged(masterTxEntity);
+        roleManagerSpy.close();
+        inOrder.verify(entityOwnershipListenerRegistration, Mockito.calls(2)).close();
+        inOrder.verify(roleManagerSpy).removeDeviceFromOperationalDS(nodeId);
+        inOrder.verifyNoMoreInteractions();
+    }
+
+    @Test
+    public void testCloseSlave() throws Exception {
+        roleManagerSpy.ownershipChanged(slaveEntity);
+        roleManagerSpy.close();
+        inOrder.verify(entityOwnershipListenerRegistration, Mockito.calls(2)).close();
+        inOrder.verify(roleManagerSpy, Mockito.never()).removeDeviceFromOperationalDS(nodeId);
+        inOrder.verifyNoMoreInteractions();
+    }
+
+    @Test
+    public void testOnDeviceContextLevelDown() throws Exception {
+        roleManagerSpy.onDeviceContextLevelDown(deviceContext);
+        inOrder.verify(roleManagerSpy).onDeviceContextLevelDown(deviceContext);
+        inOrder.verifyNoMoreInteractions();
+    }
+
+    @Test
+    public void testOwnershipChanged1() throws Exception {
+        roleManagerSpy.ownershipChanged(masterEntity);
+        inOrder.verify(roleManagerSpy, Mockito.calls(1)).changeOwnershipForMainEntity(Mockito.<EntityOwnershipChange>any(),Mockito.<RoleContext>any());
+        inOrder.verifyNoMoreInteractions();
+    }
+
+    @Test
+    public void testOwnershipChanged2() throws Exception {
+        roleManagerSpy.ownershipChanged(masterEntity);
+        roleManagerSpy.ownershipChanged(masterTxEntity);
+        inOrder.verify(roleManagerSpy, Mockito.calls(1)).changeOwnershipForTxEntity(Mockito.<EntityOwnershipChange>any(),Mockito.<RoleContext>any());
+        inOrder.verify(roleManagerSpy, Mockito.calls(1)).makeDeviceRoleChange(Mockito.<OfpRole>any(), Mockito.<RoleContext>any(), Mockito.anyBoolean());
+        inOrder.verifyNoMoreInteractions();
+    }
+
+    @Test
+    public void testChangeOwnershipForMainEntity() throws Exception {
+        roleManagerSpy.changeOwnershipForMainEntity(masterEntity, roleContextSpy);
+        inOrder.verify(roleContextSpy, Mockito.atLeastOnce()).isMainCandidateRegistered();
+        inOrder.verify(roleContextSpy, Mockito.atLeastOnce()).registerCandidate(Mockito.<Entity>any());
+    }
+
+    @Test
+    public void testChangeOwnershipForMainEntity2() throws Exception {
+        Mockito.when(roleContextSpy.isMainCandidateRegistered()).thenReturn(false);
+        roleManagerSpy.changeOwnershipForMainEntity(masterEntity, roleContextSpy);
+        inOrder.verify(roleContextSpy, Mockito.atLeastOnce()).isMainCandidateRegistered();
+    }
+
+    @Test
+    public void testChangeOwnershipForTxEntity() throws Exception {
+        Mockito.when(roleContextSpy.isTxCandidateRegistered()).thenReturn(true);
+        roleManagerSpy.changeOwnershipForTxEntity(slaveTxEntityLast, roleContextSpy);
+        inOrder.verify(roleContextSpy, Mockito.atLeastOnce()).isTxCandidateRegistered();
+        inOrder.verify(roleContextSpy, Mockito.calls(1)).unregisterCandidate(Mockito.<Entity>any());
+        inOrder.verify(roleContextSpy, Mockito.never()).close();
+        inOrder.verify(roleManagerSpy, Mockito.calls(1)).removeDeviceFromOperationalDS(Mockito.<NodeId>any());
+    }
+
+    @Test
+    public void testChangeOwnershipForTxEntity2() throws Exception {
+        roleManagerSpy.changeOwnershipForMainEntity(masterEntity, roleContextSpy);
+        roleManagerSpy.changeOwnershipForTxEntity(masterTxEntity, roleContextSpy);
+        inOrder.verify(roleContextSpy, Mockito.atLeastOnce()).isMainCandidateRegistered();
+        inOrder.verify(roleContextSpy, Mockito.calls(1)).registerCandidate(Mockito.<Entity>any());
+        inOrder.verify(roleContextSpy, Mockito.atLeastOnce()).isTxCandidateRegistered();
+        inOrder.verify(roleManagerSpy, Mockito.calls(1)).makeDeviceRoleChange(Mockito.<OfpRole>any(), Mockito.<RoleContext>any(), Mockito.anyBoolean());
+    }
+
+    @Test
+    public void testAddListener() throws Exception {
+        roleManager.addRoleChangeListener((new RoleChangeListener() {
+            @Override
+            public void roleInitializationDone(final NodeId nodeId, final boolean success) {
+                Assert.assertTrue(nodeId.equals(nodeId));
+                Assert.assertTrue(success);
+            }
+
+            @Override
+            public void roleChangeOnDevice(final NodeId nodeId_, final boolean success, final OfpRole newRole, final boolean initializationPhase) {
+                Assert.assertTrue(nodeId.equals(nodeId_));
+                Assert.assertTrue(success);
+                Assert.assertFalse(initializationPhase);
+                Assert.assertTrue(newRole.equals(OfpRole.BECOMEMASTER));
+            }
+        }));
+        roleManager.notifyListenersRoleInitializationDone(nodeId, true);
+        roleManager.notifyListenersRoleChangeOnDevice(nodeId, true, OfpRole.BECOMEMASTER, false);
+    }
+
+
+}
\ No newline at end of file
index cee4e6691611de54905c00e4426bc5a460852ddb..75b20cb7e578d7745da7692ee6aae09b014658df 100644 (file)
@@ -20,6 +20,7 @@ import org.opendaylight.controller.sal.binding.api.BindingAwareBroker;
 import org.opendaylight.openflowplugin.api.openflow.device.DeviceContext;
 import org.opendaylight.openflowplugin.api.openflow.device.DeviceState;
 import org.opendaylight.openflowplugin.api.openflow.device.RequestContext;
+import org.opendaylight.openflowplugin.api.openflow.device.XidSequencer;
 import org.opendaylight.openflowplugin.api.openflow.rpc.RpcContext;
 import org.opendaylight.openflowplugin.api.openflow.statistics.ofpspecific.MessageSpy;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
@@ -36,15 +37,13 @@ import org.opendaylight.yangtools.yang.binding.KeyedInstanceIdentifier;
 public class RpcContextImplTest {
 
     @Mock
-    private BindingAwareBroker.ProviderContext mockedRpcProviderRegistry;
+    private BindingAwareBroker.ProviderContext rpcProviderRegistry;
     @Mock
     private DeviceState deviceState;
     @Mock
-    private DeviceContext deviceContext;
+    private XidSequencer xidSequencer;
     @Mock
     private MessageSpy messageSpy;
-    @Mock
-    private NotificationPublishService notificationPublishService;
 
     private KeyedInstanceIdentifier<Node, NodeKey> nodeInstanceIdentifier;
 
@@ -52,20 +51,12 @@ public class RpcContextImplTest {
     public void setup() {
         final NodeId nodeId = new NodeId("openflow:1");
         nodeInstanceIdentifier = InstanceIdentifier.create(Nodes.class).child(Node.class, new NodeKey(nodeId));
-
-        when(deviceState.getNodeInstanceIdentifier()).thenReturn(nodeInstanceIdentifier);
-        when(deviceContext.getDeviceState()).thenReturn(deviceState);
-    }
-
-    @Test
-    public void invokeRpcTest() {
-
     }
 
     @Test
     public void testStoreOrFail() throws Exception {
-        try (final RpcContext rpcContext = new RpcContextImpl(messageSpy, mockedRpcProviderRegistry, deviceContext,
-                100, false, notificationPublishService)) {
+        try (final RpcContext rpcContext = new RpcContextImpl(rpcProviderRegistry, xidSequencer,
+                messageSpy, 100, nodeInstanceIdentifier)) {
             final RequestContext<?> requestContext = rpcContext.createRequestContext();
             assertNotNull(requestContext);
         }
@@ -73,8 +64,8 @@ public class RpcContextImplTest {
 
     @Test
     public void testStoreOrFailThatFails() throws Exception {
-        try (final RpcContext rpcContext = new RpcContextImpl(messageSpy, mockedRpcProviderRegistry, deviceContext, 0,
-                false, notificationPublishService)) {
+        try (final RpcContext rpcContext = new RpcContextImpl(rpcProviderRegistry, xidSequencer,
+                messageSpy, 0, nodeInstanceIdentifier)) {
             final RequestContext<?> requestContext = rpcContext.createRequestContext();
             assertNull(requestContext);
         }
index d6fc0786afd575aaedef888a7109872563fb8f01..3d4a67d8c575141c5224b848e06b9d7b2a79e24c 100644 (file)
@@ -7,10 +7,11 @@
  */
 package org.opendaylight.openflowplugin.impl.rpc;
 
-import static org.mockito.Mockito.times;
-
+import com.google.common.base.VerifyException;
 import org.junit.Before;
+import org.junit.Rule;
 import org.junit.Test;
+import org.junit.rules.ExpectedException;
 import org.junit.runner.RunWith;
 import org.mockito.Matchers;
 import org.mockito.Mock;
@@ -21,11 +22,13 @@ import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.ProviderCo
 import org.opendaylight.openflowplugin.api.OFConstants;
 import org.opendaylight.openflowplugin.api.openflow.connection.ConnectionContext;
 import org.opendaylight.openflowplugin.api.openflow.device.DeviceContext;
+import org.opendaylight.openflowplugin.api.openflow.device.DeviceManager;
 import org.opendaylight.openflowplugin.api.openflow.device.DeviceState;
 import org.opendaylight.openflowplugin.api.openflow.device.handlers.DeviceInitializationPhaseHandler;
+import org.opendaylight.openflowplugin.api.openflow.lifecycle.LifecycleConductor;
 import org.opendaylight.openflowplugin.api.openflow.registry.ItemLifeCycleRegistry;
 import org.opendaylight.openflowplugin.api.openflow.statistics.ofpspecific.MessageSpy;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeContext;
+import org.opendaylight.openflowplugin.impl.LifecycleConductorImpl;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
@@ -39,9 +42,9 @@ import org.opendaylight.yangtools.yang.binding.RpcService;
 @RunWith(MockitoJUnitRunner.class)
 public class RpcManagerImplTest {
 
-    private static final int AWAITED_NUM_OF_CALL_ADD_ROUTED_RPC = 12;
-
+    private static final int QUOTA_VALUE = 5;
     private RpcManagerImpl rpcManager;
+
     @Mock
     private ProviderContext rpcProviderRegistry;
     @Mock
@@ -49,50 +52,40 @@ public class RpcManagerImplTest {
     @Mock
     private DeviceInitializationPhaseHandler deviceINitializationPhaseHandler;
     @Mock
-    private ConnectionContext connectionContext;
-    @Mock
-    private BindingAwareBroker.RoutedRpcRegistration<RpcService> routedRpcRegistration;
-    @Mock
     private DeviceState deviceState;
     @Mock
-    private ItemLifeCycleRegistry itemLifeCycleRegistry;
+    private MessageSpy mockMsgSpy;
     @Mock
-    private MessageSpy messageSpy;
+    private LifecycleConductor conductor;
+
+    @Rule
+    public ExpectedException expectedException = ExpectedException.none();
 
     private KeyedInstanceIdentifier<Node, NodeKey> nodePath;
 
+    private NodeId nodeId = new NodeId("openflow-junit:1");
+
     @Before
     public void setUp() {
-        final NodeKey nodeKey = new NodeKey(new NodeId("openflow-junit:1"));
-        nodePath = KeyedInstanceIdentifier.create(Nodes.class).child(Node.class, nodeKey);
-        rpcManager = new RpcManagerImpl(rpcProviderRegistry, 5);
+        final NodeKey nodeKey = new NodeKey(nodeId);
+        rpcManager = new RpcManagerImpl(rpcProviderRegistry, QUOTA_VALUE, conductor);
         rpcManager.setDeviceInitializationPhaseHandler(deviceINitializationPhaseHandler);
-        FeaturesReply features = new GetFeaturesOutputBuilder()
-                .setVersion(OFConstants.OFP_VERSION_1_3)
-                .build();
-        Mockito.when(connectionContext.getFeatures()).thenReturn(features);
-        Mockito.when(deviceContext.getPrimaryConnectionContext()).thenReturn(connectionContext);
         Mockito.when(deviceContext.getDeviceState()).thenReturn(deviceState);
-        Mockito.when(deviceContext.getDeviceState().getRole()).thenReturn(OfpRole.BECOMEMASTER);
-        Mockito.when(deviceContext.getItemLifeCycleSourceRegistry()).thenReturn(itemLifeCycleRegistry);
-        Mockito.when(deviceState.getNodeInstanceIdentifier()).thenReturn(nodePath);
-        Mockito.when(deviceContext.getMessageSpy()).thenReturn(messageSpy);
+        Mockito.when(deviceContext.getMessageSpy()).thenReturn(mockMsgSpy);
         Mockito.when(deviceState.getNodeId()).thenReturn(nodeKey.getId());
+        Mockito.when(conductor.getDeviceContext(Mockito.<NodeId>any())).thenReturn(deviceContext);
     }
 
     @Test
-    public void testOnDeviceContextLevelUp() throws Exception {
-
-        Mockito.when(rpcProviderRegistry.addRoutedRpcImplementation(
-                Matchers.<Class<RpcService>>any(), Matchers.any(RpcService.class)))
-                .thenReturn(routedRpcRegistration);
-
-        rpcManager.onDeviceContextLevelUp(deviceContext);
+    public void onDeviceContextLevelUp() throws Exception {
+        rpcManager.onDeviceContextLevelUp(nodeId);
+        Mockito.verify(conductor).getDeviceContext(Mockito.<NodeId>any());
+    }
 
-        Mockito.verify(rpcProviderRegistry, times(AWAITED_NUM_OF_CALL_ADD_ROUTED_RPC)).addRoutedRpcImplementation(
-                Matchers.<Class<RpcService>>any(), Matchers.any(RpcService.class));
-        Mockito.verify(routedRpcRegistration, times(AWAITED_NUM_OF_CALL_ADD_ROUTED_RPC)).registerPath(
-                NodeContext.class, nodePath);
-        Mockito.verify(deviceINitializationPhaseHandler).onDeviceContextLevelUp(deviceContext);
+    @Test
+    public void onDeviceContextLevelUpTwice() throws Exception {
+        rpcManager.onDeviceContextLevelUp(nodeId);
+        expectedException.expect(VerifyException.class);
+        rpcManager.onDeviceContextLevelUp(nodeId);
     }
 }
index 68d05e435aa9816b98414fc4ab6a3fa0dd3f973b..8d41070cbddac264106e1c63822d298ffd5cbd83 100644 (file)
@@ -147,7 +147,7 @@ public class MultipartRequestOnTheFlyCallbackTest {
     }
 
     @Test
-    public void testOnSuccessWithNotMultiNoMultipart() throws ExecutionException, InterruptedException {
+    public void testOnSuccessWithNotMultiNoMultipart() throws Exception {
         final HelloMessage mockedHelloMessage = mock(HelloMessage.class);
         multipartRequestOnTheFlyCallback.onSuccess(mockedHelloMessage);
 
@@ -176,7 +176,7 @@ public class MultipartRequestOnTheFlyCallbackTest {
      * @throws InterruptedException
      */
     @Test
-    public void testOnSuccessWithValidMultipart1() throws ExecutionException, InterruptedException {
+    public void testOnSuccessWithValidMultipart1() throws Exception {
         final MatchBuilder matchBuilder = new MatchBuilder()
                 .setMatchEntry(Collections.<MatchEntry>emptyList());
         final FlowStatsBuilder flowStatsBuilder = new FlowStatsBuilder()
@@ -234,7 +234,7 @@ public class MultipartRequestOnTheFlyCallbackTest {
      * @throws InterruptedException
      */
     @Test
-    public void testOnSuccessWithValidMultipart2() throws ExecutionException, InterruptedException {
+    public void testOnSuccessWithValidMultipart2() throws Exception {
         final MultipartReplyMessageBuilder mpReplyMessage = new MultipartReplyMessageBuilder()
                 .setType(MultipartType.OFPMPDESC)
                 .setFlags(new MultipartRequestFlags(false));
index 55c18ff541e8f2901680680a27534e99e4df44c2..011387a6d01e7f6f8ad733987805267d6512eb7b 100644 (file)
@@ -92,7 +92,6 @@ public abstract class ServiceMocking {
         when(mockedDeviceContext.getMessageSpy()).thenReturn(mockedMessagSpy);
         when(mockedDeviceContext.getDeviceFlowRegistry()).thenReturn(new DeviceFlowRegistryImpl());
         when(mockedDeviceContext.getDeviceState()).thenReturn(mockedDeviceState);
-        when(mockedDeviceContext.getTimer()).thenReturn(mock(HashedWheelTimer.class));
         when(mockedDeviceContext.getMultiMsgCollector(Matchers.<RequestContext<List<MultipartReply>>>any())).thenReturn(multiMessageCollector);
 
         setup();
index 23c01582b326ba8c98d63d337a34b9aefe597903..7c50f076e4b105381913c866473dff89468cf6df 100644 (file)
@@ -15,10 +15,13 @@ import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.when;
 
 import org.junit.Before;
+import org.mockito.Mockito;
 import org.opendaylight.openflowjava.protocol.api.connection.OutboundQueue;
 import org.opendaylight.openflowplugin.api.openflow.connection.ConnectionContext;
 import org.opendaylight.openflowplugin.api.openflow.device.DeviceContext;
+import org.opendaylight.openflowplugin.api.openflow.device.DeviceManager;
 import org.opendaylight.openflowplugin.api.openflow.device.DeviceState;
+import org.opendaylight.openflowplugin.api.openflow.lifecycle.LifecycleConductor;
 import org.opendaylight.openflowplugin.api.openflow.statistics.ofpspecific.MessageSpy;
 import org.opendaylight.openflowplugin.impl.statistics.services.dedicated.StatisticsGatheringOnTheFlyService;
 import org.opendaylight.openflowplugin.impl.statistics.services.dedicated.StatisticsGatheringService;
@@ -31,25 +34,25 @@ import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 import org.opendaylight.yangtools.yang.binding.KeyedInstanceIdentifier;
 
 
-public class StatisticsContextImpMockInitiation {
-    protected boolean isTable = false;
-    protected boolean isFlow = false;
-    protected boolean isGroup = false;
-    protected boolean isMeter = false;
-    protected boolean isPort = false;
-    protected boolean isQueue = false;
+class StatisticsContextImpMockInitiation {
+    Boolean isTable = false;
+    Boolean isFlow = false;
+    Boolean isGroup = false;
+    Boolean isMeter = false;
+    Boolean isPort = false;
+    Boolean isQueue = false;
 
     protected DeviceContext mockedDeviceContext;
-    protected StatisticsGatheringService mockedStatisticsGatheringService;
-    protected StatisticsGatheringOnTheFlyService mockedStatisticsOnFlyGatheringService;
-    protected ConnectionContext mockedConnectionContext;
-    protected FeaturesReply mockedFeatures;
+    StatisticsGatheringService mockedStatisticsGatheringService;
+    StatisticsGatheringOnTheFlyService mockedStatisticsOnFlyGatheringService;
+    ConnectionContext mockedConnectionContext;
     protected DeviceState mockedDeviceState;
+    static final KeyedInstanceIdentifier<Node, NodeKey> dummyNodeII = InstanceIdentifier.create(Nodes.class)
+            .child(Node.class, new NodeKey(new NodeId("dummyNodeId")));
     protected MessageSpy mockedMessageSpy;
     protected OutboundQueue mockedOutboundQueue;
-
-    protected static final KeyedInstanceIdentifier<Node, NodeKey> dummyNodeII = InstanceIdentifier.create(Nodes.class)
-            .child(Node.class, new NodeKey(new NodeId("dummyNodeId")));
+    protected DeviceManager mockedDeviceManager;
+    LifecycleConductor mockConductor;
 
     @Before
     public void initialize() {
@@ -57,11 +60,16 @@ public class StatisticsContextImpMockInitiation {
         mockedStatisticsGatheringService = mock(StatisticsGatheringService.class);
         mockedStatisticsOnFlyGatheringService = mock(StatisticsGatheringOnTheFlyService.class);
         mockedConnectionContext = mock(ConnectionContext.class);
-        mockedFeatures = mock(FeaturesReply.class);
+        final FeaturesReply mockedFeatures = mock(FeaturesReply.class);
         mockedDeviceState = mock(DeviceState.class);
-        mockedMessageSpy = mock(MessageSpy.class);
-        mockedOutboundQueue = mock(OutboundQueue.class);
+        final MessageSpy mockedMessageSpy = mock(MessageSpy.class);
+        final OutboundQueue mockedOutboundQueue = mock(OutboundQueue.class);
+        final DeviceManager mockedDeviceManager = mock(DeviceManager.class);
+        mockConductor = mock(LifecycleConductor.class);
 
+        when(mockedDeviceContext.getDeviceState()).thenReturn(mockedDeviceState);
+        when(mockedDeviceContext.getPrimaryConnectionContext()).thenReturn(mockedConnectionContext);
+        when(mockedDeviceContext.getMessageSpy()).thenReturn(mockedMessageSpy);
         when(mockedDeviceState.isTableStatisticsAvailable()).thenReturn(isTable);
         when(mockedDeviceState.isFlowStatisticsAvailable()).thenReturn(isFlow);
         when(mockedDeviceState.isGroupAvailable()).thenReturn(isGroup);
@@ -69,14 +77,15 @@ public class StatisticsContextImpMockInitiation {
         when(mockedDeviceState.isPortStatisticsAvailable()).thenReturn(isPort);
         when(mockedDeviceState.isQueueStatisticsAvailable()).thenReturn(isQueue);
         when(mockedDeviceState.getNodeInstanceIdentifier()).thenReturn(dummyNodeII);
-        when(mockedDeviceContext.getDeviceState()).thenReturn(mockedDeviceState);
-        when(mockedDeviceContext.getPrimaryConnectionContext()).thenReturn(mockedConnectionContext);
-        when(mockedDeviceContext.getMessageSpy()).thenReturn(mockedMessageSpy);
 
         when(mockedConnectionContext.getNodeId()).thenReturn(dummyNodeII.getKey().getId());
         when(mockedConnectionContext.getFeatures()).thenReturn(mockedFeatures);
         when(mockedConnectionContext.getConnectionState()).thenReturn(ConnectionContext.CONNECTION_STATE.WORKING);
         when(mockedConnectionContext.getOutboundQueueProvider()).thenReturn(mockedOutboundQueue);
 
+        when(mockedDeviceManager.getDeviceContextFromNodeId(Mockito.<NodeId>any())).thenReturn(mockedDeviceContext);
+        mockConductor.setSafelyDeviceManager(mockedDeviceManager);
+        when(mockConductor.getDeviceContext(Mockito.<NodeId>any())).thenReturn(mockedDeviceContext);
+
     }
 }
index 1b9f7963d68821db02f6a4fae854f2cf30961d3b..22e5bc44dd914a36eb5117aba0caa099be3a5803 100644 (file)
@@ -24,7 +24,9 @@ import java.util.concurrent.ExecutionException;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.Parameterized;
+import org.mockito.Mockito;
 import org.opendaylight.openflowplugin.api.openflow.statistics.ofpspecific.EventIdentifier;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.MultipartType;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.MultipartReply;
 import org.opendaylight.yangtools.yang.common.RpcResult;
@@ -63,7 +65,8 @@ public class StatisticsContextImplParamTest extends StatisticsContextImpMockInit
     @Test
     public void gatherDynamicDataTest() {
 
-        final StatisticsContextImpl statisticsContext = new StatisticsContextImpl(mockedDeviceContext, false);
+
+        final StatisticsContextImpl statisticsContext = new StatisticsContextImpl(mockedDeviceContext.getDeviceState().getNodeId(), false, mockConductor);
 
         final ListenableFuture<RpcResult<List<MultipartReply>>> rpcResult = immediateFuture(RpcResultBuilder.success(Collections.<MultipartReply>emptyList()).build());
         when(mockedStatisticsGatheringService.getStatisticsOfType(any(EventIdentifier.class), any(MultipartType
index 30068b88732d8d322bca312543b5268768ec05b4..91533ae80099edb90feb4e5172852ebbe2cbf0f6 100644 (file)
@@ -30,6 +30,7 @@ import org.mockito.runners.MockitoJUnitRunner;
 import org.opendaylight.openflowplugin.api.openflow.connection.ConnectionContext;
 import org.opendaylight.openflowplugin.api.openflow.device.RequestContext;
 import org.opendaylight.openflowplugin.api.openflow.statistics.ofpspecific.EventIdentifier;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.common.types.rev130731.MultipartType;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.openflow.protocol.rev130731.MultipartReply;
 import org.opendaylight.yangtools.yang.common.RpcResult;
@@ -47,12 +48,13 @@ public class StatisticsContextImplTest extends StatisticsContextImpMockInitiatio
 
     @Before
     public void setUp() throws Exception {
-        when(mockedDeviceContext.reservedXidForDeviceMessage()).thenReturn(TEST_XID);
+        when(mockedDeviceContext.reserveXidForDeviceMessage()).thenReturn(TEST_XID);
+        when(mockConductor.getDeviceContext(Mockito.<NodeId>any())).thenReturn(mockedDeviceContext);
         initStatisticsContext();
     }
 
     private void initStatisticsContext() {
-        statisticsContext = new StatisticsContextImpl(mockedDeviceContext, false);
+        statisticsContext = new StatisticsContextImpl(mockedDeviceContext.getDeviceState().getNodeId(), false, mockConductor);
         statisticsContext.setStatisticsGatheringService(mockedStatisticsGatheringService);
         statisticsContext.setStatisticsGatheringOnTheFlyService(mockedStatisticsOnFlyGatheringService);
     }
@@ -70,7 +72,7 @@ public class StatisticsContextImplTest extends StatisticsContextImpMockInitiatio
      */
     @Test
     public void testClose() throws Exception {
-        final StatisticsContextImpl statisticsContext = new StatisticsContextImpl(mockedDeviceContext, false);
+        final StatisticsContextImpl statisticsContext = new StatisticsContextImpl(mockedDeviceContext.getDeviceState().getNodeId(), false, mockConductor);
         final RequestContext<Object> requestContext = statisticsContext.createRequestContext();
         statisticsContext.close();
         try {
@@ -95,12 +97,12 @@ public class StatisticsContextImplTest extends StatisticsContextImpMockInitiatio
     @Test
     public void testGatherDynamicData_all() throws Exception {
         Mockito.reset(mockedDeviceState);
-        when(mockedDeviceState.isTableStatisticsAvailable()).thenReturn(true);
-        when(mockedDeviceState.isFlowStatisticsAvailable()).thenReturn(true);
-        when(mockedDeviceState.isGroupAvailable()).thenReturn(true);
-        when(mockedDeviceState.isMetersAvailable()).thenReturn(true);
-        when(mockedDeviceState.isPortStatisticsAvailable()).thenReturn(true);
-        when(mockedDeviceState.isQueueStatisticsAvailable()).thenReturn(true);
+        when(mockedDeviceState.isTableStatisticsAvailable()).thenReturn(Boolean.TRUE);
+        when(mockedDeviceState.isFlowStatisticsAvailable()).thenReturn(Boolean.TRUE);
+        when(mockedDeviceState.isGroupAvailable()).thenReturn(Boolean.TRUE);
+        when(mockedDeviceState.isMetersAvailable()).thenReturn(Boolean.TRUE);
+        when(mockedDeviceState.isPortStatisticsAvailable()).thenReturn(Boolean.TRUE);
+        when(mockedDeviceState.isQueueStatisticsAvailable()).thenReturn(Boolean.TRUE);
         when(mockedDeviceState.getNodeInstanceIdentifier()).thenReturn(dummyNodeII);
         initStatisticsContext();
 
index f52a56b54eb64639dc60f3e91dd4360b2ce7020a..283d0d0b87038c5dbfa448ec5857e7d96654556a 100644 (file)
@@ -188,7 +188,7 @@ public class StatisticsGatheringUtilsTest {
     }
 
     @Test
-    public void testWriteFlowStatistics() {
+    public void testWriteFlowStatistics() throws Exception {
         final ArgumentCaptor<LogicalDatastoreType> dataStoreType = ArgumentCaptor.forClass(LogicalDatastoreType.class);
         final ArgumentCaptor<InstanceIdentifier> flowPath = ArgumentCaptor.forClass(InstanceIdentifier.class);
         final ArgumentCaptor<Flow> flow = ArgumentCaptor.forClass(Flow.class);
index 7a56c8ce9c7744e067a7d6247d4e3a65bbfd466b..df14afe627374f37d6911f95074618a0d51e5e0b 100644 (file)
@@ -34,12 +34,14 @@ import org.opendaylight.openflowjava.protocol.api.connection.OutboundQueue;
 import org.opendaylight.openflowplugin.api.OFConstants;
 import org.opendaylight.openflowplugin.api.openflow.connection.ConnectionContext;
 import org.opendaylight.openflowplugin.api.openflow.device.DeviceContext;
+import org.opendaylight.openflowplugin.api.openflow.device.DeviceManager;
 import org.opendaylight.openflowplugin.api.openflow.device.DeviceState;
 import org.opendaylight.openflowplugin.api.openflow.device.RequestContext;
 import org.opendaylight.openflowplugin.api.openflow.device.RequestContextStack;
 import org.opendaylight.openflowplugin.api.openflow.device.handlers.DeviceInitializationPhaseHandler;
 import org.opendaylight.openflowplugin.api.openflow.device.handlers.DeviceTerminationPhaseHandler;
 import org.opendaylight.openflowplugin.api.openflow.device.handlers.MultiMsgCollector;
+import org.opendaylight.openflowplugin.api.openflow.lifecycle.LifecycleConductor;
 import org.opendaylight.openflowplugin.api.openflow.registry.ItemLifeCycleRegistry;
 import org.opendaylight.openflowplugin.api.openflow.rpc.ItemLifeCycleSource;
 import org.opendaylight.openflowplugin.api.openflow.rpc.listener.ItemLifecycleListener;
@@ -101,6 +103,10 @@ public class StatisticsManagerImplTest {
     private ArgumentCaptor<ItemLifecycleListener> itemLifeCycleListenerCapt;
     @Mock
     private BindingAwareBroker.RpcRegistration<StatisticsManagerControlService> serviceControlRegistration;
+    @Mock
+    private DeviceManager deviceManager;
+    @Mock
+    private LifecycleConductor conductor;
 
     private RequestContext<List<MultipartReply>> currentRequestContext;
     private StatisticsManagerImpl statisticsManager;
@@ -116,12 +122,12 @@ public class StatisticsManagerImplTest {
         when(mockedPrimConnectionContext.getNodeId()).thenReturn(new NodeId("ut-node:123"));
         when(mockedPrimConnectionContext.getOutboundQueueProvider()).thenReturn(outboundQueue);
 
-        when(mockedDeviceState.isFlowStatisticsAvailable()).thenReturn(true);
-        when(mockedDeviceState.isGroupAvailable()).thenReturn(true);
-        when(mockedDeviceState.isMetersAvailable()).thenReturn(true);
-        when(mockedDeviceState.isPortStatisticsAvailable()).thenReturn(true);
-        when(mockedDeviceState.isQueueStatisticsAvailable()).thenReturn(true);
-        when(mockedDeviceState.isTableStatisticsAvailable()).thenReturn(true);
+        when(mockedDeviceState.isFlowStatisticsAvailable()).thenReturn(Boolean.TRUE);
+        when(mockedDeviceState.isGroupAvailable()).thenReturn(Boolean.TRUE);
+        when(mockedDeviceState.isMetersAvailable()).thenReturn(Boolean.TRUE);
+        when(mockedDeviceState.isPortStatisticsAvailable()).thenReturn(Boolean.TRUE);
+        when(mockedDeviceState.isQueueStatisticsAvailable()).thenReturn(Boolean.TRUE);
+        when(mockedDeviceState.isTableStatisticsAvailable()).thenReturn(Boolean.TRUE);
 
         when(mockedDeviceState.getNodeId()).thenReturn(new NodeId("ofp-unit-dummy-node-id"));
 
@@ -129,7 +135,6 @@ public class StatisticsManagerImplTest {
         when(mockedDeviceContext.getMessageSpy()).thenReturn(mockedMessagSpy);
         when(mockedDeviceContext.getDeviceFlowRegistry()).thenReturn(new DeviceFlowRegistryImpl());
         when(mockedDeviceContext.getDeviceState()).thenReturn(mockedDeviceState);
-        when(mockedDeviceContext.getTimer()).thenReturn(hashedWheelTimer);
         when(mockedDeviceContext.getMultiMsgCollector(
                 Matchers.<RequestContext<List<MultipartReply>>>any())).thenAnswer(
                 new Answer<MultiMsgCollector>() {
@@ -145,36 +150,14 @@ public class StatisticsManagerImplTest {
                 Matchers.eq(StatisticsManagerControlService.class),
                 Matchers.<StatisticsManagerControlService>any())).thenReturn(serviceControlRegistration);
 
-        statisticsManager = new StatisticsManagerImpl(rpcProviderRegistry, false);
+        statisticsManager = new StatisticsManagerImpl(rpcProviderRegistry, false, conductor);
+        when(deviceManager.getDeviceContextFromNodeId(Mockito.<NodeId>any())).thenReturn(mockedDeviceContext);
+        when(conductor.getDeviceContext(Mockito.<NodeId>any())).thenReturn(mockedDeviceContext);
     }
 
     @Test
     public void testOnDeviceContextLevelUp() throws Exception {
-        Mockito.doAnswer(new Answer<Void>() {
-            @Override
-            public Void answer(InvocationOnMock invocation) throws Throwable {
-                final FutureCallback<OfHeader> callback = (FutureCallback<OfHeader>) invocation.getArguments()[2];
-                LOG.debug("committing entry: {}", ((MultipartRequestInput) invocation.getArguments()[1]).getType());
-                callback.onSuccess(null);
-                currentRequestContext.setResult(RpcResultBuilder.<List<MultipartReply>>success().build());
-                return null;
-            }
-        }).when(outboundQueue)
-                .commitEntry(Matchers.anyLong(), Matchers.<OfHeader>any(), Matchers.<FutureCallback<OfHeader>>any());
-
-        statisticsManager.setDeviceInitializationPhaseHandler(mockedDevicePhaseHandler);
-        statisticsManager.onDeviceContextLevelUp(mockedDeviceContext);
-
-        verify(mockedDeviceContext).addDeviceContextClosedHandler(statisticsManager);
-        verify(mockedDeviceContext, Mockito.never()).reservedXidForDeviceMessage();
-        verify(mockedDeviceState).setDeviceSynchronized(true);
-        verify(mockedDevicePhaseHandler).onDeviceContextLevelUp(mockedDeviceContext);
-        verify(hashedWheelTimer).newTimeout(Matchers.<TimerTask>any(), Matchers.anyLong(), Matchers.<TimeUnit>any());
-    }
-
-    @Test
-    public void testOnDeviceContextLevelUp1() throws Exception {
-        statisticsManager = new StatisticsManagerImpl(rpcProviderRegistry, true);
+        statisticsManager = new StatisticsManagerImpl(rpcProviderRegistry, true, conductor);
         Mockito.doAnswer(new Answer<Void>() {
             @Override
             public Void answer(final InvocationOnMock invocation) throws Throwable {
@@ -188,12 +171,11 @@ public class StatisticsManagerImplTest {
                 .commitEntry(Matchers.anyLong(), Matchers.<OfHeader>any(), Matchers.<FutureCallback<OfHeader>>any());
 
         statisticsManager.setDeviceInitializationPhaseHandler(mockedDevicePhaseHandler);
-        statisticsManager.onDeviceContextLevelUp(mockedDeviceContext);
+        statisticsManager.onDeviceContextLevelUp(mockedDeviceContext.getDeviceState().getNodeId());
 
-        verify(mockedDeviceContext).addDeviceContextClosedHandler(statisticsManager);
-        verify(mockedDeviceContext, Mockito.never()).reservedXidForDeviceMessage();
+        verify(mockedDeviceContext, Mockito.never()).reserveXidForDeviceMessage();
         verify(mockedDeviceState).setDeviceSynchronized(true);
-        verify(mockedDevicePhaseHandler).onDeviceContextLevelUp(mockedDeviceContext);
+        verify(mockedDevicePhaseHandler).onDeviceContextLevelUp(mockedDeviceContext.getDeviceState().getNodeId());
         verify(hashedWheelTimer, Mockito.never()).newTimeout(Matchers.<TimerTask>any(), Matchers.anyLong(), Matchers.<TimeUnit>any());
     }
 
@@ -250,7 +232,7 @@ public class StatisticsManagerImplTest {
                 new ChangeStatisticsWorkModeInputBuilder()
                         .setMode(StatisticsWorkMode.FULLYDISABLED);
 
-        Future<RpcResult<Void>> workMode = statisticsManager
+        final Future<RpcResult<Void>> workMode = statisticsManager
                 .changeStatisticsWorkMode(changeStatisticsWorkModeInputBld.build());
 
         checkWorkModeChangeOutcome(workMode);
@@ -303,8 +285,8 @@ public class StatisticsManagerImplTest {
      */
     @Test
     public void testChangeStatisticsWorkMode3() throws Exception {
-        Timeout pollTimeout = Mockito.mock(Timeout.class);
-        ItemLifeCycleSource itemLifecycleSource = Mockito.mock(ItemLifeCycleSource.class);
+        final Timeout pollTimeout = Mockito.mock(Timeout.class);
+        final ItemLifeCycleSource itemLifecycleSource = Mockito.mock(ItemLifeCycleSource.class);
         Mockito.doNothing().when(itemLifecycleSource)
                 .setItemLifecycleListener(itemLifeCycleListenerCapt.capture());
 
@@ -352,7 +334,7 @@ public class StatisticsManagerImplTest {
     @Test
     public void testCalculateTimerDelay() throws Exception {
         final TimeCounter timeCounter = Mockito.mock(TimeCounter.class);
-        when(timeCounter.getAverageTimeBetweenMarks()).thenReturn(2000L, 4000L);
+        when(timeCounter.getAverageTimeBetweenMarks()).thenReturn((Long)2000L, (Long)4000L);
 
         statisticsManager.calculateTimerDelay(timeCounter);
         Assert.assertEquals(3000L, StatisticsManagerImpl.getCurrentTimerDelay());
index 56850376c181f0803203a55ca16db05121f0cf55..4fd14992fb5ecf71c5a79b979dd5c663e8e911ee 100644 (file)
@@ -144,8 +144,8 @@ public class DeviceInitializationUtilsTest {
         when(mockFeatures.getDatapathId()).thenReturn(BigInteger.valueOf(21L));
     }
     @Test
-    public void chainTableTrunkWriteOF10Test() {
-        final DeviceState mockedDeviceState = mock(DeviceState.class);
+    public void chainTableTrunkWriteOF10Test() throws Exception {
+        DeviceState mockedDeviceState = mock(DeviceState.class);
 
         final GetFeaturesOutput mockedFeatures = mock(GetFeaturesOutput.class);
         when(mockedFeatures.getTables()).thenReturn((short) 2);
@@ -166,7 +166,7 @@ public class DeviceInitializationUtilsTest {
     }
 
     @Test
-    public void testTranslateAndWriteReplyTypeDesc() {
+    public void testTranslateAndWriteReplyTypeDesc() throws Exception {
         final ConnectionContext connectionContext = buildMockConnectionContext(OFConstants.OFP_VERSION_1_3);
         Mockito.when(mockedDeviceContext.getPrimaryConnectionContext()).thenReturn(connectionContext);
         final DeviceState deviceState = Mockito.mock(DeviceState.class);
@@ -180,8 +180,8 @@ public class DeviceInitializationUtilsTest {
     }
 
     @Test
-    public void translateAndWriteReplyTypeTableFeatures() {
-        final TableFeaturesBuilder tableFeature = new TableFeaturesBuilder();
+    public void translateAndWriteReplyTypeTableFeatures() throws Exception {
+        TableFeaturesBuilder tableFeature = new TableFeaturesBuilder();
         tableFeature.setTableId(DUMMY_TABLE_ID);
         final List<TableFeatures> tableFeatures = new ArrayList<>();
         tableFeatures.add(tableFeature.build());
@@ -200,8 +200,8 @@ public class DeviceInitializationUtilsTest {
     }
 
     @Test
-    public void translateAndWriteReplyTypeMeterFeatures() {
-        final DeviceState mockedDeviceState = mock(DeviceState.class);
+    public void translateAndWriteReplyTypeMeterFeatures() throws Exception {
+        DeviceState mockedDeviceState = mock(DeviceState.class);
         when(mockedDeviceContext.getDeviceState()).thenReturn(mockedDeviceState);
 
         final MultipartReplyMeterFeaturesBuilder multipartReplyMeterFeaturesBuilder = new MultipartReplyMeterFeaturesBuilder();
@@ -221,8 +221,8 @@ public class DeviceInitializationUtilsTest {
     }
 
     @Test
-    public void translateAndWriteReplyTypeGroupFeatures() {
-        final MultipartReplyGroupFeaturesBuilder multipartReplyGroupFeaturesBuilder = new MultipartReplyGroupFeaturesBuilder();
+    public void translateAndWriteReplyTypeGroupFeatures() throws Exception {
+        MultipartReplyGroupFeaturesBuilder multipartReplyGroupFeaturesBuilder = new MultipartReplyGroupFeaturesBuilder();
         multipartReplyGroupFeaturesBuilder.setTypes(new GroupTypes(true, true, true, true));
         multipartReplyGroupFeaturesBuilder.setCapabilities(new GroupCapabilities(true, true, true, true));
         final ActionType actionType = new ActionType(true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true);
@@ -243,9 +243,9 @@ public class DeviceInitializationUtilsTest {
 
 
     @Test
-    public void translateAndWriteReplyTypePortDesc() {
-        final ConnectionContext mockedPrimaryConnectionContext = mock(ConnectionContext.class);
-        final FeaturesReply mockedFeatures = mock(FeaturesReply.class);
+    public void translateAndWriteReplyTypePortDesc() throws Exception {
+        ConnectionContext mockedPrimaryConnectionContext = mock(ConnectionContext.class);
+        FeaturesReply mockedFeatures = mock(FeaturesReply.class);
         when(mockedFeatures.getDatapathId()).thenReturn(new BigInteger(DUMMY_DATAPATH_ID));
         when(mockedPrimaryConnectionContext.getFeatures()).thenReturn(mockedFeatures);
         when(mockedDeviceContext.getPrimaryConnectionContext()).thenReturn(mockedPrimaryConnectionContext);
@@ -276,8 +276,8 @@ public class DeviceInitializationUtilsTest {
     }
 
     @Test
-    public void createSuccessProcessingCallbackTest() {
-        final DeviceState mockedDeviceState = mock(DeviceState.class);
+    public void createSuccessProcessingCallbackTest() throws Exception {
+        DeviceState mockedDeviceState = mock(DeviceState.class);
         when(mockedDeviceContext.getDeviceState()).thenReturn(mockedDeviceState);
 
         final ConnectionContext connectionContext = buildMockConnectionContext(OFConstants.OFP_VERSION_1_3);
index daffbf396b6f955784410824f0dcdcfd3fe4bc36..60f8f9ae8626c7ab2f5732577cc2e6fff8c38b6c 100644 (file)
@@ -42,7 +42,7 @@ public class OpenflowPortsUtil {
                 .put(OutputPortValues.ALL.toString(), Long.valueOf(PortNumberValuesV10.ALL.getIntValue())) //0xfffc
                 .put(OutputPortValues.CONTROLLER.toString(), Long.valueOf(PortNumberValuesV10.CONTROLLER.getIntValue())) //0xfffd
                 .put(OutputPortValues.LOCAL.toString(), Long.valueOf(PortNumberValuesV10.LOCAL.getIntValue())) //0xfffe
-                .put(OutputPortValues.NONE.toString(), Long.valueOf(PortNumberValuesV10.NONE.getIntValue())) //0xfffe
+                .put(OutputPortValues.NONE.toString(), Long.valueOf(PortNumberValuesV10.NONE.getIntValue())) //0xffff
                 .build();
 
         // openflow 1.3 reserved ports.
index c7baf79270bd21ccc98438a054e63f02feab40cc..55d68f818b8a1bf8d15f87c72aa93cae3cb4d4d0 100644 (file)
@@ -31,7 +31,6 @@
 
     <properties>
         <project.build.sourceEncoding>utf-8</project.build.sourceEncoding>
-        <nexusproxy>http://nexus.opendaylight.org/content</nexusproxy>
         <openflowjava.version>0.8.0-SNAPSHOT</openflowjava.version>
         <openflowplugin.version>0.3.0-SNAPSHOT</openflowplugin.version>
         <sal.api.version>0.11.0-SNAPSHOT</sal.api.version>