Fix problem with unregistering from cluster services.
[openflowplugin.git] / openflowplugin-impl / src / main / java / org / opendaylight / openflowplugin / impl / lifecycle / ContextChainImpl.java
1 /*
2  * Copyright (c) 2016 Pantheon Technologies s.r.o. 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 package org.opendaylight.openflowplugin.impl.lifecycle;
9
10 import com.google.common.base.Function;
11 import com.google.common.util.concurrent.Futures;
12 import com.google.common.util.concurrent.ListenableFuture;
13 import java.util.ArrayList;
14 import java.util.HashSet;
15 import java.util.List;
16 import java.util.Set;
17 import javax.annotation.Nullable;
18 import org.eclipse.jdt.annotation.NonNull;
19 import org.opendaylight.mdsal.singleton.common.api.ClusterSingletonServiceProvider;
20 import org.opendaylight.openflowplugin.api.openflow.OFPContext;
21 import org.opendaylight.openflowplugin.api.openflow.connection.ConnectionContext;
22 import org.opendaylight.openflowplugin.api.openflow.device.DeviceContext;
23 import org.opendaylight.openflowplugin.api.openflow.lifecycle.ContextChain;
24 import org.opendaylight.openflowplugin.api.openflow.lifecycle.LifecycleService;
25 import org.opendaylight.openflowplugin.api.openflow.rpc.RpcContext;
26 import org.opendaylight.openflowplugin.api.openflow.statistics.StatisticsContext;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.openflow.provider.config.rev160510.ContextChainState;
28 import org.slf4j.Logger;
29 import org.slf4j.LoggerFactory;
30
31 public class ContextChainImpl implements ContextChain {
32
33     private static final Logger LOG = LoggerFactory.getLogger(ContextChainImpl.class);
34
35     private Set<OFPContext> contexts = new HashSet<>();
36     private StatisticsContext statisticsContext;
37     private DeviceContext deviceContext;
38     private RpcContext rpcContext;
39     private volatile ContextChainState contextChainState;
40     private LifecycleService lifecycleService;
41     private ConnectionContext primaryConnectionContext;
42
43     public ContextChainImpl() {
44         this.contextChainState = ContextChainState.INITIALIZED;
45     }
46
47     @Override
48     public <T extends OFPContext> void addContext(final T context) {
49         if (context instanceof StatisticsContext) {
50             this.statisticsContext = (StatisticsContext) context;
51         } else {
52             if (context instanceof DeviceContext) {
53                 this.deviceContext = (DeviceContext) context;
54             } else {
55                 if (context instanceof RpcContext) {
56                     this.rpcContext = (RpcContext) context;
57                 }
58             }
59         }
60         contexts.add(context);
61     }
62
63     @Override
64     public void addLifecycleService(final LifecycleService lifecycleService) {
65         this.lifecycleService = lifecycleService;
66     }
67
68     @Override
69     public ListenableFuture<Void> stopChain(boolean connectionDropped) {
70         //TODO: stopClusterServices change parameter
71         final List<ListenableFuture<Void>> futureList = new ArrayList<>();
72         futureList.add(statisticsContext.stopClusterServices());
73         futureList.add(rpcContext.stopClusterServices());
74         futureList.add(deviceContext.stopClusterServices(connectionDropped));
75
76         return Futures.transform(Futures.successfulAsList(futureList), new Function<List<Void>, Void>() {
77             @Nullable
78             @Override
79             public Void apply(@Nullable List<Void> input) {
80                 LOG.debug("Closed clustering MASTER services for node {}", deviceContext.getDeviceInfo().getLOGValue());
81                 return null;
82             }
83         });
84     }
85
86     @Override
87     public ListenableFuture<Void> startChain() {
88         if (ContextChainState.INITIALIZED.equals(this.contextChainState)) {
89             return Futures.transform(this.statisticsContext.initialGatherDynamicData(), new Function<Boolean, Void>() {
90                 @Nullable
91                 @Override
92                 public Void apply(@Nullable Boolean aBoolean) {
93                     contextChainState = ContextChainState.WORKINGMASTER;
94                     return null;
95                 }
96             });
97         } else {
98             this.contextChainState = ContextChainState.WORKINGMASTER;
99         }
100         return Futures.immediateFuture(null);
101     }
102
103     @Override
104     public void close() {
105         deviceContext.close();
106         rpcContext.close();
107         statisticsContext.close();
108         lifecycleService.close();
109     }
110
111     @Override
112     public void changePrimaryConnection(final ConnectionContext connectionContext) {
113         this.primaryConnectionContext = connectionContext;
114         this.contextChainState = ContextChainState.INITIALIZED;
115         for (OFPContext context : contexts) {
116             context.replaceConnection(connectionContext);
117         }
118     }
119
120     @Override
121     public ContextChainState getContextChainState() {
122         return contextChainState;
123     }
124
125     @Override
126     public ListenableFuture<Void> connectionDropped() {
127         ContextChainState oldState = this.contextChainState;
128         this.contextChainState = ContextChainState.SLEEPING;
129         if (oldState.equals(ContextChainState.WORKINGMASTER)) {
130             return this.stopChain(true);
131         }
132         return Futures.immediateFuture(null);
133     }
134
135     @Override
136     public void sleepTheChainAndDropConnection() {
137         this.contextChainState = ContextChainState.SLEEPING;
138         this.primaryConnectionContext.closeConnection(true);
139     }
140
141     @Override
142     public void registerServices(@NonNull final ClusterSingletonServiceProvider clusterSingletonServiceProvider) {
143         this.contextChainState = ContextChainState.WORKINGSLAVE;
144         this.lifecycleService.registerService(
145                 clusterSingletonServiceProvider,
146                 this.deviceContext,
147                 this.deviceContext.getServiceIdentifier(),
148                 this.deviceContext.getDeviceInfo());
149     }
150
151     @Override
152     public void makeDeviceSlave() {
153         this.lifecycleService.makeDeviceSlave(this.deviceContext);
154     }
155
156     @Override
157     public void closePrimaryConnection() {
158         this.primaryConnectionContext.closeConnection(true);
159     }
160
161     @Override
162     public DeviceContext provideDeviceContext() {
163         return this.deviceContext;
164     }
165
166     @Override
167     public void sleepTheChain() {
168         this.contextChainState = ContextChainState.SLEEPING;
169         this.stopChain(true);
170     }
171 }