Merge "Bug 4957 TxChainManager lifecycle startup cleaning"
[openflowplugin.git] / applications / topology-manager / src / main / java / org / opendaylight / openflowplugin / applications / topology / manager / FlowCapableTopologyProvider.java
1 /*
2  * Copyright (c) 2013 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 package org.opendaylight.openflowplugin.applications.topology.manager;
9
10 import java.util.concurrent.ExecutionException;
11
12 import com.google.common.base.Optional;
13 import org.opendaylight.controller.md.sal.binding.api.DataBroker;
14 import org.opendaylight.controller.md.sal.binding.api.ReadTransaction;
15 import org.opendaylight.controller.md.sal.binding.api.ReadWriteTransaction;
16 import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
17 import org.opendaylight.controller.md.sal.common.api.data.ReadFailedException;
18 import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.ProviderContext;
19 import org.opendaylight.controller.sal.binding.api.BindingAwareProvider;
20 import org.opendaylight.controller.sal.binding.api.NotificationProviderService;
21 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopology;
22 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.TopologyId;
23 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology;
24 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.TopologyBuilder;
25 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.TopologyKey;
26 import org.opendaylight.yangtools.concepts.ListenerRegistration;
27 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
28 import org.opendaylight.yangtools.yang.binding.NotificationListener;
29 import org.slf4j.Logger;
30 import org.slf4j.LoggerFactory;
31
32 public class FlowCapableTopologyProvider implements BindingAwareProvider, AutoCloseable {
33     private static final Logger LOG = LoggerFactory.getLogger(FlowCapableTopologyProvider.class);
34     private ListenerRegistration<NotificationListener> listenerRegistration;
35     private Thread thread;
36     private TerminationPointChangeListenerImpl terminationPointChangeListener;
37     private NodeChangeListenerImpl nodeChangeListener;
38     static final String TOPOLOGY_ID = "flow:1";
39
40     /**
41      * Gets called on start of a bundle.
42      *
43      * @param session
44      */
45     @Override
46     public synchronized void onSessionInitiated(final ProviderContext session) {
47         final DataBroker dataBroker = session.getSALService(DataBroker.class);
48         final NotificationProviderService notificationService = session.getSALService(NotificationProviderService.class);
49
50         final TopologyKey key = new TopologyKey(new TopologyId(TOPOLOGY_ID));
51         final InstanceIdentifier<Topology> path = InstanceIdentifier
52                 .create(NetworkTopology.class)
53                 .child(Topology.class, key);
54
55         final OperationProcessor processor = new OperationProcessor(dataBroker);
56         final FlowCapableTopologyExporter listener = new FlowCapableTopologyExporter(processor, path);
57         this.listenerRegistration = notificationService.registerNotificationListener(listener);
58         this.terminationPointChangeListener = new TerminationPointChangeListenerImpl(dataBroker, processor);
59         nodeChangeListener = new NodeChangeListenerImpl(dataBroker, processor);
60
61         if(!isFlowTopologyExist(dataBroker, path)){
62             final ReadWriteTransaction tx = dataBroker.newReadWriteTransaction();
63             tx.put(LogicalDatastoreType.OPERATIONAL, path, new TopologyBuilder().setKey(key).build(), true);
64             try {
65                 tx.submit().get();
66             } catch (InterruptedException | ExecutionException e) {
67                 LOG.warn("Initial topology export failed, continuing anyway", e);
68             }
69         }
70
71         thread = new Thread(processor);
72         thread.setDaemon(true);
73         thread.setName("FlowCapableTopologyExporter-" + TOPOLOGY_ID);
74         thread.start();
75     }
76
77     @Override
78     public synchronized void close() throws InterruptedException {
79         LOG.info("FlowCapableTopologyProvider stopped.");
80         if (this.listenerRegistration != null) {
81             try {
82                 this.listenerRegistration.close();
83             } catch (Exception e) {
84                 LOG.warn("Failed to close listener registration: {}", e.getMessage());
85                 LOG.debug("Failed to close listener registration.. ", e);
86             }
87             listenerRegistration = null;
88         }
89         unregisterListener(terminationPointChangeListener);
90         unregisterListener(nodeChangeListener);
91         if (thread != null) {
92             thread.interrupt();
93             thread.join();
94             thread = null;
95         }
96     }
97
98     private static void unregisterListener(final AutoCloseable listenerToClose) {
99         if (listenerToClose != null) {
100             try {
101                 listenerToClose.close();
102             } catch (Exception e) {
103                 LOG.warn("Failed to close listener registration: {}", e.getMessage());
104                 LOG.debug("Failed to close listener registration.. ", e);
105             }
106         }
107     }
108
109     private boolean isFlowTopologyExist(final DataBroker dataBroker,
110                                         final InstanceIdentifier<Topology> path) {
111         final ReadTransaction tx = dataBroker.newReadOnlyTransaction();
112         try {
113             Optional<Topology> ofTopology = tx.read(LogicalDatastoreType.OPERATIONAL, path).checkedGet();
114             LOG.debug("OpenFlow topology exist in the operational data store at {}",path);
115             if(ofTopology.isPresent()){
116                 return true;
117             }
118         } catch (ReadFailedException e) {
119             LOG.warn("OpenFlow topology read operation failed!", e);
120         }
121         return false;
122     }
123 }