Bug 4957 No empty transaction for every connection fix
[openflowplugin.git] / applications / forwardingrules-manager / src / main / java / org / opendaylight / openflowplugin / applications / frm / impl / ForwardingRulesManagerImpl.java
1 /**
2  * Copyright (c) 2014, 2015 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.applications.frm.impl;
10
11 import com.google.common.base.Optional;
12 import com.google.common.base.Preconditions;
13 import com.google.common.collect.Sets;
14 import java.util.Collections;
15 import java.util.Set;
16 import java.util.concurrent.atomic.AtomicLong;
17
18 import com.google.common.util.concurrent.CheckedFuture;
19 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
20 import org.opendaylight.controller.md.sal.binding.api.ReadOnlyTransaction;
21 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
22 import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
23 import org.opendaylight.controller.sal.binding.api.RpcConsumerRegistry;
24 import org.opendaylight.openflowplugin.applications.frm.FlowNodeReconciliation;
25 import org.opendaylight.openflowplugin.applications.frm.ForwardingRulesCommiter;
26 import org.opendaylight.openflowplugin.applications.frm.ForwardingRulesManager;
27 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.meters.Meter;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.table.Flow;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.flow.service.rev130819.SalFlowService;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.service.rev130918.SalGroupService;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.group.types.rev131018.groups.Group;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.meter.service.rev130918.SalMeterService;
35 import org.opendaylight.yang.gen.v1.urn.opendaylight.table.types.rev131026.table.features.TableFeatures;
36 import org.opendaylight.yang.gen.v1.urn.opendaylight.table.service.rev131026.SalTableService;
37 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
38 import org.slf4j.Logger;
39 import org.slf4j.LoggerFactory;
40
41 /**
42  * forwardingrules-manager
43  * org.opendaylight.openflowplugin.applications.frm.impl
44  *
45  * Manager and middle point for whole module.
46  * It contains ActiveNodeHolder and provide all RPC services.
47  *
48  * @author <a href="mailto:vdemcak@cisco.com">Vaclav Demcak</a>
49  *
50  * Created: Aug 25, 2014
51  */
52 public class ForwardingRulesManagerImpl implements ForwardingRulesManager {
53
54     private static final Logger LOG = LoggerFactory.getLogger(ForwardingRulesManagerImpl.class);
55     public static final int STARTUP_LOOP_TICK = 500;
56     public static final int STARTUP_LOOP_MAX_RETRIES = 8;
57
58     private final AtomicLong txNum = new AtomicLong();
59     private final Object lockObj = new Object();
60     private Set<InstanceIdentifier<FlowCapableNode>> activeNodes = Collections.emptySet();
61
62     private final DataBroker dataService;
63     private final SalFlowService salFlowService;
64     private final SalGroupService salGroupService;
65     private final SalMeterService salMeterService;
66     private final SalTableService salTableService;
67
68     private ForwardingRulesCommiter<Flow> flowListener;
69     private ForwardingRulesCommiter<Group> groupListener;
70     private ForwardingRulesCommiter<Meter> meterListener;
71     private ForwardingRulesCommiter<TableFeatures> tableListener;
72     private FlowNodeReconciliation nodeListener;
73
74     private final ForwardingRulesManagerConfig forwardingRulesManagerConfig;
75
76     public ForwardingRulesManagerImpl(final DataBroker dataBroker,
77                                       final RpcConsumerRegistry rpcRegistry,
78                                       final ForwardingRulesManagerConfig config) {
79         this.dataService = Preconditions.checkNotNull(dataBroker, "DataBroker can not be null!");
80         this.forwardingRulesManagerConfig = Preconditions.checkNotNull(config, "Configuration for FRM cannot be null");
81
82         Preconditions.checkArgument(rpcRegistry != null, "RpcConsumerRegistry can not be null !");
83
84         this.salFlowService = Preconditions.checkNotNull(rpcRegistry.getRpcService(SalFlowService.class),
85                 "RPC SalFlowService not found.");
86         this.salGroupService = Preconditions.checkNotNull(rpcRegistry.getRpcService(SalGroupService.class),
87                 "RPC SalGroupService not found.");
88         this.salMeterService = Preconditions.checkNotNull(rpcRegistry.getRpcService(SalMeterService.class),
89                 "RPC SalMeterService not found.");
90         this.salTableService = Preconditions.checkNotNull(rpcRegistry.getRpcService(SalTableService.class),
91                 "RPC SalTableService not found.");
92     }
93
94     @Override
95     public void start() {
96
97         this.flowListener = new FlowForwarder(this, dataService);
98
99         this.groupListener = new GroupForwarder(this, dataService);
100         this.meterListener = new MeterForwarder(this, dataService);
101
102         this.tableListener = new TableForwarder(this, dataService);
103         this.nodeListener = new FlowNodeReconciliationImpl(this, dataService);
104         LOG.info("ForwardingRulesManager has started successfully.");
105
106     }
107
108     @Override
109     public void close() throws Exception {
110         if (this.flowListener != null) {
111             this.flowListener.close();
112             this.flowListener = null;
113         }
114         if (this.groupListener != null) {
115             this.groupListener.close();
116             this.groupListener = null;
117         }
118         if (this.meterListener != null) {
119             this.meterListener.close();
120             this.meterListener = null;
121         }
122         if (this.tableListener != null) {
123             this.tableListener.close();
124             this.tableListener = null;
125         }
126         if (this.nodeListener != null) {
127             this.nodeListener.close();
128             this.nodeListener = null;
129         }
130     }
131
132     @Override
133     public ReadOnlyTransaction getReadTranaction() {
134         return dataService.newReadOnlyTransaction();
135     }
136
137     @Override
138     public String getNewTransactionId() {
139         return "DOM-" + txNum.getAndIncrement();
140     }
141
142     @Override
143     public boolean isNodeActive(InstanceIdentifier<FlowCapableNode> ident) {
144         return activeNodes.contains(ident);
145     }
146
147     @Override
148     public boolean checkNodeInOperationalDataStore(InstanceIdentifier<FlowCapableNode> ident) {
149         boolean result = false;
150         InstanceIdentifier<Node> nodeIid = ident.firstIdentifierOf(Node.class);
151         final ReadOnlyTransaction transaction = dataService.newReadOnlyTransaction();
152         Optional<Node> optionalDataObject;
153         CheckedFuture<Optional<Node>, ReadFailedException> future = transaction.read(LogicalDatastoreType.OPERATIONAL, nodeIid);
154         try {
155             optionalDataObject = future.checkedGet();
156             if (optionalDataObject.isPresent()) {
157                 result = true;
158             } else {
159                 LOG.debug("{}: Failed to read {}",
160                         Thread.currentThread().getStackTrace()[1], nodeIid);
161             }
162         } catch (ReadFailedException e) {
163             LOG.warn("Failed to read {} ", nodeIid, e);
164         }
165         transaction.close();
166
167         return result;
168     }
169
170     @Override
171     public void registrateNewNode(InstanceIdentifier<FlowCapableNode> ident) {
172         if (!activeNodes.contains(ident)) {
173             synchronized (lockObj) {
174                 if (!activeNodes.contains(ident)) {
175                     Set<InstanceIdentifier<FlowCapableNode>> set =
176                             Sets.newHashSet(activeNodes);
177                     set.add(ident);
178                     activeNodes = Collections.unmodifiableSet(set);
179                 }
180             }
181         }
182     }
183
184     @Override
185     public void unregistrateNode(InstanceIdentifier<FlowCapableNode> ident) {
186         if (activeNodes.contains(ident)) {
187             synchronized (lockObj) {
188                 if (activeNodes.contains(ident)) {
189                     Set<InstanceIdentifier<FlowCapableNode>> set =
190                             Sets.newHashSet(activeNodes);
191                     set.remove(ident);
192                     activeNodes = Collections.unmodifiableSet(set);
193                 }
194             }
195         }
196     }
197
198     @Override
199     public SalFlowService getSalFlowService() {
200         return salFlowService;
201     }
202
203     @Override
204     public SalGroupService getSalGroupService() {
205         return salGroupService;
206     }
207
208     @Override
209     public SalMeterService getSalMeterService() {
210         return salMeterService;
211     }
212
213     @Override
214     public SalTableService getSalTableService() {
215         return salTableService;
216     }
217
218     @Override
219     public ForwardingRulesCommiter<Flow> getFlowCommiter() {
220         return flowListener;
221     }
222
223     @Override
224     public ForwardingRulesCommiter<Group> getGroupCommiter() {
225         return groupListener;
226     }
227
228     @Override
229     public ForwardingRulesCommiter<Meter> getMeterCommiter() {
230         return meterListener;
231     }
232
233     @Override
234     public ForwardingRulesCommiter<TableFeatures> getTableFeaturesCommiter() {
235         return tableListener;
236     }
237
238     @Override
239     public FlowNodeReconciliation getFlowNodeReconciliation() {
240         return nodeListener;
241     }
242
243     @Override
244     public ForwardingRulesManagerConfig getConfiguration() {
245         return forwardingRulesManagerConfig;
246     }
247 }
248