Topology manager: get rid of sychronized sections
[controller.git] / opendaylight / md-sal / topology-manager / src / main / java / org / opendaylight / md / controller / topology / manager / FlowCapableTopologyProvider.java
index e77ba8769cbcdbd0f51b65820855e5beb7687f0a..d656bda932f2251e18ea7f71f6c19500115456d3 100644 (file)
@@ -7,11 +7,20 @@
  */
 package org.opendaylight.md.controller.topology.manager;
 
+import java.util.concurrent.ExecutionException;
+
 import org.opendaylight.controller.sal.binding.api.AbstractBindingAwareProvider;
 import org.opendaylight.controller.sal.binding.api.BindingAwareBroker.ProviderContext;
 import org.opendaylight.controller.sal.binding.api.NotificationProviderService;
+import org.opendaylight.controller.sal.binding.api.data.DataModificationTransaction;
 import org.opendaylight.controller.sal.binding.api.data.DataProviderService;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopology;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.TopologyId;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.TopologyBuilder;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.TopologyKey;
 import org.opendaylight.yangtools.concepts.Registration;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 import org.opendaylight.yangtools.yang.binding.NotificationListener;
 import org.osgi.framework.BundleContext;
 import org.slf4j.Logger;
@@ -19,58 +28,60 @@ import org.slf4j.LoggerFactory;
 
 public class FlowCapableTopologyProvider extends AbstractBindingAwareProvider implements AutoCloseable {
     private final static Logger LOG = LoggerFactory.getLogger(FlowCapableTopologyProvider.class);
+    private Registration<NotificationListener> listenerRegistration;
+    private Thread thread;
 
-    private DataProviderService dataService;
-
-    public DataProviderService getDataService() {
-        return this.dataService;
-    }
+    /**
+     * Gets called on start of a bundle.
+     *
+     * @param session
+     */
+    @Override
+    public synchronized void onSessionInitiated(final ProviderContext session) {
+        final DataProviderService dataService = session.getSALService(DataProviderService.class);
+        final NotificationProviderService notificationService = session.getSALService(NotificationProviderService.class);
 
-    public void setDataService(final DataProviderService dataService) {
-        this.dataService = dataService;
-    }
+        final String name = "flow:1";
+        final TopologyKey key = new TopologyKey(new TopologyId(name));
+        final InstanceIdentifier<Topology> path = InstanceIdentifier
+                .builder(NetworkTopology.class)
+                .child(Topology.class, key)
+                .build();
 
-    private NotificationProviderService notificationService;
+        final OperationProcessor processor = new OperationProcessor(dataService);
+        final FlowCapableTopologyExporter listener = new FlowCapableTopologyExporter(processor, path);
+        this.listenerRegistration = notificationService.registerNotificationListener(listener);
 
-    public NotificationProviderService getNotificationService() {
-        return this.notificationService;
-    }
+        final DataModificationTransaction tx = dataService.beginTransaction();
+        tx.putOperationalData(path, new TopologyBuilder().setKey(key).build());
+        try {
+            tx.commit().get();
+        } catch (InterruptedException | ExecutionException e) {
+            LOG.warn("Initial topology export failed, continuing anyway", e);
+        }
 
-    public void setNotificationService(final NotificationProviderService notificationService) {
-        this.notificationService = notificationService;
+        thread = new Thread(processor);
+        thread.setDaemon(true);
+        thread.setName("FlowCapableTopologyExporter-" + name);
+        thread.start();
     }
 
-    private final FlowCapableTopologyExporter exporter = new FlowCapableTopologyExporter();
-    private Registration<NotificationListener> listenerRegistration;
-
     @Override
-    public void close() {
-
-        FlowCapableTopologyProvider.LOG.info("FlowCapableTopologyProvider stopped.");
-        dataService = null;
-        notificationService = null;
+    public synchronized void close() throws InterruptedException {
+        LOG.info("FlowCapableTopologyProvider stopped.");
         if (this.listenerRegistration != null) {
             try {
                 this.listenerRegistration.close();
             } catch (Exception e) {
-                throw new IllegalStateException("Exception during close of listener registration.",e);
+                LOG.error("Failed to close listener registration", e);
             }
+            listenerRegistration = null;
+        }
+        if (thread != null) {
+            thread.interrupt();
+            thread.join();
+            thread = null;
         }
-    }
-
-    /**
-     * Gets called on start of a bundle.
-     *
-     * @param session
-     */
-    @Override
-    public void onSessionInitiated(final ProviderContext session) {
-        dataService = session.getSALService(DataProviderService.class);
-        notificationService = session.getSALService(NotificationProviderService.class);
-        this.exporter.setDataService(dataService);
-        this.exporter.start();
-        this.listenerRegistration = notificationService.registerNotificationListener(this.exporter);
-        ;
     }
 
     /**
@@ -81,6 +92,10 @@ public class FlowCapableTopologyProvider extends AbstractBindingAwareProvider im
      */
     @Override
     public void stopImpl(final BundleContext context) {
-        this.close();
+        try {
+            this.close();
+        } catch (InterruptedException e) {
+            LOG.error("Failed to stop provider", e);
+        }
     }
 }