Fix unused import warnings
[openflowplugin.git] / openflowplugin-impl / src / main / java / org / opendaylight / openflowplugin / impl / LifecycleConductorImpl.java
1 /*
2  * Copyright (c) 2016 Cisco Systems, Inc. and others.  All rights reserved.
3  *
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
7  */
8
9 package org.opendaylight.openflowplugin.impl;
10
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 java.util.Map;
20 import java.util.concurrent.ConcurrentHashMap;
21 import java.util.concurrent.TimeUnit;
22 import javax.annotation.Nonnull;
23 import javax.annotation.Nullable;
24 import org.opendaylight.openflowplugin.api.openflow.connection.ConnectionContext;
25 import org.opendaylight.openflowplugin.api.openflow.device.DeviceContext;
26 import org.opendaylight.openflowplugin.api.openflow.device.DeviceManager;
27 import org.opendaylight.openflowplugin.api.openflow.lifecycle.DeviceContextChangeListener;
28 import org.opendaylight.openflowplugin.api.openflow.lifecycle.LifecycleConductor;
29 import org.opendaylight.openflowplugin.api.openflow.lifecycle.RoleChangeListener;
30 import org.opendaylight.openflowplugin.api.openflow.lifecycle.ServiceChangeListener;
31 import org.opendaylight.openflowplugin.api.openflow.statistics.StatisticsManager;
32 import org.opendaylight.openflowplugin.api.openflow.statistics.ofpspecific.MessageIntelligenceAgency;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.NodeId;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.role.service.rev150727.OfpRole;
35 import org.slf4j.Logger;
36 import org.slf4j.LoggerFactory;
37
38 /**
39  */
40 public final class LifecycleConductorImpl implements LifecycleConductor, RoleChangeListener, DeviceContextChangeListener {
41
42     private static final Logger LOG = LoggerFactory.getLogger(LifecycleConductorImpl.class);
43     private static final int TICKS_PER_WHEEL = 500;
44     private static final long TICK_DURATION = 10; // 0.5 sec.
45
46     private final HashedWheelTimer hashedWheelTimer = new HashedWheelTimer(TICK_DURATION, TimeUnit.MILLISECONDS, TICKS_PER_WHEEL);
47     private DeviceManager deviceManager;
48     private final MessageIntelligenceAgency messageIntelligenceAgency;
49     private ConcurrentHashMap<NodeId, ServiceChangeListener> serviceChangeListeners = new ConcurrentHashMap<>();
50     private StatisticsManager statisticsManager;
51
52     public LifecycleConductorImpl(final MessageIntelligenceAgency messageIntelligenceAgency) {
53         Preconditions.checkNotNull(messageIntelligenceAgency);
54         this.messageIntelligenceAgency = messageIntelligenceAgency;
55     }
56
57     public void setSafelyDeviceManager(final DeviceManager deviceManager) {
58         if (this.deviceManager == null) {
59             this.deviceManager = deviceManager;
60         }
61     }
62
63     public void setSafelyStatisticsManager(final StatisticsManager statisticsManager) {
64         if (this.statisticsManager == null) {
65             this.statisticsManager = statisticsManager;
66         }
67     }
68
69     public void addOneTimeListenerWhenServicesChangesDone(final ServiceChangeListener manager, final NodeId nodeId){
70         LOG.debug("Listener {} for service change for node {} registered.", manager, nodeId);
71         serviceChangeListeners.put(nodeId, manager);
72     }
73
74     @VisibleForTesting
75     void notifyServiceChangeListeners(final NodeId nodeId, final boolean success){
76         if (serviceChangeListeners.size() == 0) {
77             return;
78         }
79         LOG.debug("Notifying registered listeners for service change, no. of listeners {}", serviceChangeListeners.size());
80         for (final Map.Entry<NodeId, ServiceChangeListener> nodeIdServiceChangeListenerEntry : serviceChangeListeners.entrySet()) {
81             if (nodeIdServiceChangeListenerEntry.getKey().equals(nodeId)) {
82                 LOG.debug("Listener {} for service change for node {} was notified. Success was set on {}", nodeIdServiceChangeListenerEntry.getValue(), nodeId, success);
83                 nodeIdServiceChangeListenerEntry.getValue().servicesChangeDone(nodeId, success);
84                 serviceChangeListeners.remove(nodeId);
85             }
86         }
87     }
88
89     @Override
90     public void roleInitializationDone(final NodeId nodeId, final boolean success) {
91         if (!success) {
92             LOG.warn("Initialization phase for node {} in role context was NOT successful, closing connection.", nodeId);
93             closeConnection(nodeId);
94         } else {
95             LOG.info("initialization phase for node {} in role context was successful, continuing to next context.", nodeId);
96         }
97     }
98
99     public void closeConnection(final NodeId nodeId) {
100         LOG.debug("Close connection called for node {}", nodeId);
101         final DeviceContext deviceContext = getDeviceContext(nodeId);
102         if (null != deviceContext) {
103             deviceContext.shutdownConnection();
104         }
105     }
106
107     @Override
108     public void roleChangeOnDevice(final NodeId nodeId, final boolean success, final OfpRole newRole, final boolean initializationPhase) {
109
110         final DeviceContext deviceContext = getDeviceContext(nodeId);
111
112         if (null == deviceContext) {
113             LOG.warn("Something went wrong, device context for nodeId: {} doesn't exists");
114             return;
115         }
116         if (!success) {
117             LOG.warn("Role change to {} in role context for node {} was NOT successful, closing connection", newRole, nodeId);
118             closeConnection(nodeId);
119         } else {
120             if (initializationPhase) {
121                 LOG.debug("Initialization phase skipping starting services.");
122                 return;
123             }
124
125             LOG.info("Role change to {} in role context for node {} was successful, starting/stopping services.", newRole, nodeId);
126
127             if (OfpRole.BECOMEMASTER.equals(newRole)) {
128                 statisticsManager.startScheduling(nodeId);
129             } else {
130                 statisticsManager.stopScheduling(nodeId);
131             }
132
133             final ListenableFuture<Void> onClusterRoleChange = deviceContext.onClusterRoleChange(null, newRole);
134             Futures.addCallback(onClusterRoleChange, new FutureCallback<Void>() {
135                 @Override
136                 public void onSuccess(@Nullable final Void aVoid) {
137                     LOG.info("Starting/Stopping services for node {} was successful", nodeId);
138                     if (newRole.equals(OfpRole.BECOMESLAVE)) notifyServiceChangeListeners(nodeId, true);
139                 }
140
141                 @Override
142                 public void onFailure(final Throwable throwable) {
143                     LOG.warn("Starting/Stopping services for node {} was NOT successful, closing connection", nodeId);
144                     closeConnection(nodeId);
145                 }
146             });
147         }
148     }
149
150     public MessageIntelligenceAgency getMessageIntelligenceAgency() {
151         return messageIntelligenceAgency;
152     }
153
154     @Override
155     public DeviceContext getDeviceContext(final NodeId nodeId){
156          return deviceManager.getDeviceContextFromNodeId(nodeId);
157     }
158
159     public Short gainVersionSafely(final NodeId nodeId) {
160         return (null != getDeviceContext(nodeId)) ? getDeviceContext(nodeId).getPrimaryConnectionContext().getFeatures().getVersion() : null;
161     }
162
163     public Timeout newTimeout(@Nonnull TimerTask task, long delay, @Nonnull TimeUnit unit) {
164         return hashedWheelTimer.newTimeout(task, delay, unit);
165     }
166
167     public ConnectionContext.CONNECTION_STATE gainConnectionStateSafely(final NodeId nodeId){
168         return (null != getDeviceContext(nodeId)) ? getDeviceContext(nodeId).getPrimaryConnectionContext().getConnectionState() : null;
169     }
170
171     public Long reserveXidForDeviceMessage(final NodeId nodeId){
172         return null != getDeviceContext(nodeId) ? getDeviceContext(nodeId).reserveXidForDeviceMessage() : null;
173     }
174
175     @Override
176     public void deviceStartInitializationDone(final NodeId nodeId, final boolean success) {
177         if (!success) {
178             LOG.warn("Initialization phase for node {} in device context was NOT successful, closing connection.", nodeId);
179             closeConnection(nodeId);
180         } else {
181             LOG.info("initialization phase for node {} in device context was successful. Continuing to next context.", nodeId);
182         }
183     }
184
185     @Override
186     public void deviceInitializationDone(final NodeId nodeId, final boolean success) {
187         if (!success) {
188             LOG.warn("Initialization phase for node {} in device context was NOT successful, closing connection.", nodeId);
189             closeConnection(nodeId);
190         } else {
191             LOG.info("initialization phase for node {} in device context was successful. All phases initialized OK.", nodeId);
192         }
193     }
194
195     @VisibleForTesting
196     public boolean isServiceChangeListenersEmpty() {
197         return this.serviceChangeListeners.isEmpty();
198     }
199
200 }