2 * Copyright (c) 2016 Cisco Systems, Inc. and others. All rights reserved.
4 * This program and the accompanying materials are made available under the
5 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6 * and is available at http://www.eclipse.org/legal/epl-v10.html
9 package org.opendaylight.openflowplugin.impl;
11 import com.google.common.annotations.VisibleForTesting;
12 import com.google.common.base.Preconditions;
13 import com.google.common.util.concurrent.FutureCallback;
14 import com.google.common.util.concurrent.Futures;
15 import com.google.common.util.concurrent.ListenableFuture;
16 import io.netty.util.HashedWheelTimer;
17 import io.netty.util.Timeout;
18 import io.netty.util.TimerTask;
19 import org.opendaylight.openflowplugin.api.openflow.connection.ConnectionContext;
20 import org.opendaylight.openflowplugin.api.openflow.device.DeviceContext;
21 import org.opendaylight.openflowplugin.api.openflow.device.DeviceManager;
22 import org.opendaylight.openflowplugin.api.openflow.device.DeviceState;
23 import org.opendaylight.openflowplugin.api.openflow.lifecycle.DeviceContextChangeListener;
24 import org.opendaylight.openflowplugin.api.openflow.lifecycle.LifecycleConductor;
25 import org.opendaylight.openflowplugin.api.openflow.lifecycle.RoleChangeListener;
26 import org.opendaylight.openflowplugin.api.openflow.lifecycle.ServiceChangeListener;
27 import org.opendaylight.openflowplugin.api.openflow.statistics.StatisticsManager;
28 import org.opendaylight.openflowplugin.api.openflow.statistics.ofpspecific.MessageIntelligenceAgency;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.role.service.rev150727.OfpRole;
31 import org.slf4j.Logger;
32 import org.slf4j.LoggerFactory;
34 import javax.annotation.Nonnull;
35 import javax.annotation.Nullable;
37 import java.util.concurrent.ConcurrentHashMap;
38 import java.util.concurrent.TimeUnit;
42 public final class LifecycleConductorImpl implements LifecycleConductor, RoleChangeListener, DeviceContextChangeListener {
44 private static final Logger LOG = LoggerFactory.getLogger(LifecycleConductorImpl.class);
45 private static final int TICKS_PER_WHEEL = 500;
46 private static final long TICK_DURATION = 10; // 0.5 sec.
48 private final HashedWheelTimer hashedWheelTimer = new HashedWheelTimer(TICK_DURATION, TimeUnit.MILLISECONDS, TICKS_PER_WHEEL);
49 private DeviceManager deviceManager;
50 private final MessageIntelligenceAgency messageIntelligenceAgency;
51 private ConcurrentHashMap<NodeId, ServiceChangeListener> serviceChangeListeners = new ConcurrentHashMap<>();
52 private StatisticsManager statisticsManager;
54 public LifecycleConductorImpl(final MessageIntelligenceAgency messageIntelligenceAgency) {
55 Preconditions.checkNotNull(messageIntelligenceAgency);
56 this.messageIntelligenceAgency = messageIntelligenceAgency;
59 public void setSafelyDeviceManager(final DeviceManager deviceManager) {
60 if (this.deviceManager == null) {
61 this.deviceManager = deviceManager;
65 public void setSafelyStatisticsManager(final StatisticsManager statisticsManager) {
66 if (this.statisticsManager == null) {
67 this.statisticsManager = statisticsManager;
71 public void addOneTimeListenerWhenServicesChangesDone(final ServiceChangeListener manager, final NodeId nodeId){
72 LOG.debug("Listener {} for service change for node {} registered.", manager, nodeId);
73 serviceChangeListeners.put(nodeId, manager);
77 void notifyServiceChangeListeners(final NodeId nodeId, final boolean success){
78 if (serviceChangeListeners.size() == 0) {
81 LOG.debug("Notifying registered listeners for service change, no. of listeners {}", serviceChangeListeners.size());
82 for (final Map.Entry<NodeId, ServiceChangeListener> nodeIdServiceChangeListenerEntry : serviceChangeListeners.entrySet()) {
83 if (nodeIdServiceChangeListenerEntry.getKey().equals(nodeId)) {
84 LOG.debug("Listener {} for service change for node {} was notified. Success was set on {}", nodeIdServiceChangeListenerEntry.getValue(), nodeId, success);
85 nodeIdServiceChangeListenerEntry.getValue().servicesChangeDone(nodeId, success);
86 serviceChangeListeners.remove(nodeId);
92 public void roleInitializationDone(final NodeId nodeId, final boolean success) {
94 LOG.warn("Initialization phase for node {} in role context was NOT successful, closing connection.", nodeId);
95 closeConnection(nodeId);
97 LOG.info("initialization phase for node {} in role context was successful, continuing to next context.", nodeId);
101 public void closeConnection(final NodeId nodeId) {
102 LOG.debug("Close connection called for node {}", nodeId);
103 final DeviceContext deviceContext = getDeviceContext(nodeId);
104 if (null != deviceContext) {
105 deviceContext.shutdownConnection();
110 public void roleChangeOnDevice(final NodeId nodeId, final boolean success, final OfpRole newRole, final boolean initializationPhase) {
112 final DeviceContext deviceContext = getDeviceContext(nodeId);
114 if (null == deviceContext) {
115 LOG.warn("Something went wrong, device context for nodeId: {} doesn't exists");
119 LOG.warn("Role change to {} in role context for node {} was NOT successful, closing connection", newRole, nodeId);
120 closeConnection(nodeId);
122 if (initializationPhase) {
123 LOG.debug("Initialization phase skipping starting services.");
127 LOG.info("Role change to {} in role context for node {} was successful, starting/stopping services.", newRole, nodeId);
129 if (OfpRole.BECOMEMASTER.equals(newRole)) {
130 statisticsManager.startScheduling(nodeId);
132 statisticsManager.stopScheduling(nodeId);
135 final ListenableFuture<Void> onClusterRoleChange = deviceContext.onClusterRoleChange(null, newRole);
136 Futures.addCallback(onClusterRoleChange, new FutureCallback<Void>() {
138 public void onSuccess(@Nullable final Void aVoid) {
139 LOG.info("Starting/Stopping services for node {} was successful", nodeId);
140 if (newRole.equals(OfpRole.BECOMESLAVE)) notifyServiceChangeListeners(nodeId, true);
144 public void onFailure(final Throwable throwable) {
145 LOG.warn("Starting/Stopping services for node {} was NOT successful, closing connection", nodeId);
146 closeConnection(nodeId);
152 public MessageIntelligenceAgency getMessageIntelligenceAgency() {
153 return messageIntelligenceAgency;
157 public DeviceContext getDeviceContext(final NodeId nodeId){
158 return deviceManager.getDeviceContextFromNodeId(nodeId);
161 public Short gainVersionSafely(final NodeId nodeId) {
162 return (null != getDeviceContext(nodeId)) ? getDeviceContext(nodeId).getPrimaryConnectionContext().getFeatures().getVersion() : null;
165 public Timeout newTimeout(@Nonnull TimerTask task, long delay, @Nonnull TimeUnit unit) {
166 return hashedWheelTimer.newTimeout(task, delay, unit);
169 public ConnectionContext.CONNECTION_STATE gainConnectionStateSafely(final NodeId nodeId){
170 return (null != getDeviceContext(nodeId)) ? getDeviceContext(nodeId).getPrimaryConnectionContext().getConnectionState() : null;
173 public Long reserveXidForDeviceMessage(final NodeId nodeId){
174 return null != getDeviceContext(nodeId) ? getDeviceContext(nodeId).reserveXidForDeviceMessage() : null;
178 public void deviceStartInitializationDone(final NodeId nodeId, final boolean success) {
180 LOG.warn("Initialization phase for node {} in device context was NOT successful, closing connection.", nodeId);
181 closeConnection(nodeId);
183 LOG.info("initialization phase for node {} in device context was successful. Continuing to next context.", nodeId);
188 public void deviceInitializationDone(final NodeId nodeId, final boolean success) {
190 LOG.warn("Initialization phase for node {} in device context was NOT successful, closing connection.", nodeId);
191 closeConnection(nodeId);
193 LOG.info("initialization phase for node {} in device context was successful. All phases initialized OK.", nodeId);
198 public boolean isServiceChangeListenersEmpty() {
199 return this.serviceChangeListeners.isEmpty();