Factor out SchemaResourceManager 71/89371/11
authorRobert Varga <robert.varga@pantheon.tech>
Sat, 25 Apr 2020 09:46:44 +0000 (11:46 +0200)
committerRobert Varga <robert.varga@pantheon.tech>
Mon, 27 Apr 2020 18:26:10 +0000 (20:26 +0200)
Management of schema cache on the filesystem is copy&pasted in two
places, which creates a compatibility problem. Furthermore current
code relies on static wiring, which is going to be non-workable
very soon.

Refactor AbstractTopology to split out schema management into a
separate component within sal-netconf-connector, which is injected
into both AbstractTopology subclasses and clustered topology.

JIRA: NETCONF-672
Change-Id: If1284a08f9525a3396f2d39e2a4399366edee7ae
Signed-off-by: Robert Varga <robert.varga@pantheon.tech>
22 files changed:
netconf/callhome-provider/src/main/java/org/opendaylight/netconf/callhome/mount/BaseCallHomeTopology.java
netconf/callhome-provider/src/main/java/org/opendaylight/netconf/callhome/mount/CallHomeMountDispatcher.java
netconf/callhome-provider/src/main/java/org/opendaylight/netconf/callhome/mount/CallHomeTopology.java
netconf/callhome-provider/src/main/resources/OSGI-INF/blueprint/callhome-topology.xml
netconf/callhome-provider/src/test/java/org/opendaylight/netconf/callhome/mount/CallHomeMountDispatcherTest.java
netconf/netconf-topology-impl/src/main/java/org/opendaylight/netconf/topology/impl/NetconfTopologyImpl.java
netconf/netconf-topology-impl/src/main/resources/OSGI-INF/blueprint/netconf-topology.xml
netconf/netconf-topology-impl/src/test/java/org/opendaylight/netconf/topology/impl/NetconfTopologyImplTest.java
netconf/netconf-topology-singleton/src/main/java/org/opendaylight/netconf/topology/singleton/impl/NetconfTopologyManager.java
netconf/netconf-topology-singleton/src/main/java/org/opendaylight/netconf/topology/singleton/impl/utils/NetconfTopologyUtils.java
netconf/netconf-topology-singleton/src/main/resources/OSGI-INF/blueprint/netconf-topology-singleton.xml
netconf/netconf-topology-singleton/src/test/java/org/opendaylight/netconf/topology/singleton/impl/MountPointEndToEndTest.java
netconf/netconf-topology-singleton/src/test/java/org/opendaylight/netconf/topology/singleton/impl/NetconfNodeActorTest.java
netconf/netconf-topology-singleton/src/test/java/org/opendaylight/netconf/topology/singleton/impl/NetconfTopologyManagerTest.java
netconf/netconf-topology-singleton/src/test/java/org/opendaylight/netconf/topology/singleton/impl/RemoteDeviceConnectorImplTest.java
netconf/netconf-topology/src/main/java/org/opendaylight/netconf/topology/api/SchemaRepositoryProvider.java [deleted file]
netconf/netconf-topology/src/main/java/org/opendaylight/netconf/topology/spi/AbstractNetconfTopology.java
netconf/netconf-topology/src/main/java/org/opendaylight/netconf/topology/spi/SharedSchemaRepositoryProvider.java [deleted file]
netconf/sal-netconf-connector/pom.xml
netconf/sal-netconf-connector/src/main/java/org/opendaylight/netconf/sal/connect/api/SchemaResourceManager.java [new file with mode: 0644]
netconf/sal-netconf-connector/src/main/java/org/opendaylight/netconf/sal/connect/impl/DefaultSchemaResourceManager.java [new file with mode: 0644]
netconf/sal-netconf-connector/src/main/resources/OSGI-INF/blueprint/sal-netconf-connector.xml

index 1405267c2dabe6a08e54ed5441c74e919f4a9b5d..844e474586d617cddc7462d12322a820d16a93e0 100644 (file)
@@ -15,7 +15,7 @@ import org.opendaylight.mdsal.binding.api.DataBroker;
 import org.opendaylight.mdsal.dom.api.DOMMountPointService;
 import org.opendaylight.netconf.client.NetconfClientDispatcher;
 import org.opendaylight.netconf.sal.connect.api.DeviceActionFactory;
 import org.opendaylight.mdsal.dom.api.DOMMountPointService;
 import org.opendaylight.netconf.client.NetconfClientDispatcher;
 import org.opendaylight.netconf.sal.connect.api.DeviceActionFactory;
-import org.opendaylight.netconf.topology.api.SchemaRepositoryProvider;
+import org.opendaylight.netconf.sal.connect.api.SchemaResourceManager;
 import org.opendaylight.netconf.topology.spi.AbstractNetconfTopology;
 
 abstract class BaseCallHomeTopology extends AbstractNetconfTopology {
 import org.opendaylight.netconf.topology.spi.AbstractNetconfTopology;
 
 abstract class BaseCallHomeTopology extends AbstractNetconfTopology {
@@ -23,7 +23,7 @@ abstract class BaseCallHomeTopology extends AbstractNetconfTopology {
                          final EventExecutor eventExecutor,
                          final ScheduledThreadPool keepaliveExecutor,
                          final ThreadPool processingExecutor,
                          final EventExecutor eventExecutor,
                          final ScheduledThreadPool keepaliveExecutor,
                          final ThreadPool processingExecutor,
-                         final SchemaRepositoryProvider schemaRepositoryProvider,
+                         final SchemaResourceManager schemaRepositoryProvider,
                          final DataBroker dataBroker,
                          final DOMMountPointService mountPointService,
                          final AAAEncryptionService encryptionService,
                          final DataBroker dataBroker,
                          final DOMMountPointService mountPointService,
                          final AAAEncryptionService encryptionService,
index b73cddfda47cca9000e0f427c2f59108b517b166..de843caab21ff7826fb247e8cfb5725b28b9ca7a 100644 (file)
@@ -25,7 +25,7 @@ import org.opendaylight.netconf.client.NetconfClientSession;
 import org.opendaylight.netconf.client.conf.NetconfClientConfiguration;
 import org.opendaylight.netconf.client.conf.NetconfReconnectingClientConfiguration;
 import org.opendaylight.netconf.sal.connect.api.DeviceActionFactory;
 import org.opendaylight.netconf.client.conf.NetconfClientConfiguration;
 import org.opendaylight.netconf.client.conf.NetconfReconnectingClientConfiguration;
 import org.opendaylight.netconf.sal.connect.api.DeviceActionFactory;
-import org.opendaylight.netconf.topology.api.SchemaRepositoryProvider;
+import org.opendaylight.netconf.sal.connect.api.SchemaResourceManager;
 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
 import org.slf4j.Logger;
 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
 import org.slf4j.Logger;
@@ -39,7 +39,7 @@ public class CallHomeMountDispatcher implements NetconfClientDispatcher, CallHom
     private final EventExecutor eventExecutor;
     private final ScheduledThreadPool keepaliveExecutor;
     private final ThreadPool processingExecutor;
     private final EventExecutor eventExecutor;
     private final ScheduledThreadPool keepaliveExecutor;
     private final ThreadPool processingExecutor;
-    private final SchemaRepositoryProvider schemaRepositoryProvider;
+    private final SchemaResourceManager schemaRepositoryProvider;
     private final CallHomeMountSessionManager sessionManager;
     private final DataBroker dataBroker;
     private final DOMMountPointService mountService;
     private final CallHomeMountSessionManager sessionManager;
     private final DataBroker dataBroker;
     private final DOMMountPointService mountService;
@@ -56,7 +56,7 @@ public class CallHomeMountDispatcher implements NetconfClientDispatcher, CallHom
 
     public CallHomeMountDispatcher(final String topologyId, final EventExecutor eventExecutor,
                                    final ScheduledThreadPool keepaliveExecutor, final ThreadPool processingExecutor,
 
     public CallHomeMountDispatcher(final String topologyId, final EventExecutor eventExecutor,
                                    final ScheduledThreadPool keepaliveExecutor, final ThreadPool processingExecutor,
-                                   final SchemaRepositoryProvider schemaRepositoryProvider, final DataBroker dataBroker,
+                                   final SchemaResourceManager schemaRepositoryProvider, final DataBroker dataBroker,
                                    final DOMMountPointService mountService,
                                    final AAAEncryptionService encryptionService) {
         this(topologyId, eventExecutor, keepaliveExecutor, processingExecutor, schemaRepositoryProvider, dataBroker,
                                    final DOMMountPointService mountService,
                                    final AAAEncryptionService encryptionService) {
         this(topologyId, eventExecutor, keepaliveExecutor, processingExecutor, schemaRepositoryProvider, dataBroker,
@@ -65,7 +65,7 @@ public class CallHomeMountDispatcher implements NetconfClientDispatcher, CallHom
 
     public CallHomeMountDispatcher(final String topologyId, final EventExecutor eventExecutor,
             final ScheduledThreadPool keepaliveExecutor, final ThreadPool processingExecutor,
 
     public CallHomeMountDispatcher(final String topologyId, final EventExecutor eventExecutor,
             final ScheduledThreadPool keepaliveExecutor, final ThreadPool processingExecutor,
-            final SchemaRepositoryProvider schemaRepositoryProvider, final DataBroker dataBroker,
+            final SchemaResourceManager schemaRepositoryProvider, final DataBroker dataBroker,
             final DOMMountPointService mountService,
             final AAAEncryptionService encryptionService, final DeviceActionFactory deviceActionFactory) {
         this.topologyId = topologyId;
             final DOMMountPointService mountService,
             final AAAEncryptionService encryptionService, final DeviceActionFactory deviceActionFactory) {
         this.topologyId = topologyId;
index e032637cd83b2886584013e841edbfea29945d3a..f6f185dc05ab3d2d2392ac41797963c26dd749ad 100644 (file)
@@ -16,17 +16,17 @@ import org.opendaylight.mdsal.dom.api.DOMMountPointService;
 import org.opendaylight.netconf.client.NetconfClientDispatcher;
 import org.opendaylight.netconf.sal.connect.api.DeviceActionFactory;
 import org.opendaylight.netconf.sal.connect.api.RemoteDeviceHandler;
 import org.opendaylight.netconf.client.NetconfClientDispatcher;
 import org.opendaylight.netconf.sal.connect.api.DeviceActionFactory;
 import org.opendaylight.netconf.sal.connect.api.RemoteDeviceHandler;
+import org.opendaylight.netconf.sal.connect.api.SchemaResourceManager;
 import org.opendaylight.netconf.sal.connect.netconf.listener.NetconfSessionPreferences;
 import org.opendaylight.netconf.sal.connect.netconf.sal.NetconfDeviceSalFacade;
 import org.opendaylight.netconf.sal.connect.util.RemoteDeviceId;
 import org.opendaylight.netconf.sal.connect.netconf.listener.NetconfSessionPreferences;
 import org.opendaylight.netconf.sal.connect.netconf.sal.NetconfDeviceSalFacade;
 import org.opendaylight.netconf.sal.connect.util.RemoteDeviceId;
-import org.opendaylight.netconf.topology.api.SchemaRepositoryProvider;
 
 public class CallHomeTopology extends BaseCallHomeTopology {
 
     public CallHomeTopology(final String topologyId, final NetconfClientDispatcher clientDispatcher,
             final EventExecutor eventExecutor,
             final ScheduledThreadPool keepaliveExecutor, final ThreadPool processingExecutor,
 
 public class CallHomeTopology extends BaseCallHomeTopology {
 
     public CallHomeTopology(final String topologyId, final NetconfClientDispatcher clientDispatcher,
             final EventExecutor eventExecutor,
             final ScheduledThreadPool keepaliveExecutor, final ThreadPool processingExecutor,
-            final SchemaRepositoryProvider schemaRepositoryProvider,
+            final SchemaResourceManager schemaRepositoryProvider,
             final DataBroker dataBroker, final DOMMountPointService mountPointService,
             final AAAEncryptionService encryptionService) {
         this(topologyId, clientDispatcher, eventExecutor,
             final DataBroker dataBroker, final DOMMountPointService mountPointService,
             final AAAEncryptionService encryptionService) {
         this(topologyId, clientDispatcher, eventExecutor,
@@ -37,7 +37,7 @@ public class CallHomeTopology extends BaseCallHomeTopology {
     public CallHomeTopology(final String topologyId, final NetconfClientDispatcher clientDispatcher,
                             final EventExecutor eventExecutor,
                             final ScheduledThreadPool keepaliveExecutor, final ThreadPool processingExecutor,
     public CallHomeTopology(final String topologyId, final NetconfClientDispatcher clientDispatcher,
                             final EventExecutor eventExecutor,
                             final ScheduledThreadPool keepaliveExecutor, final ThreadPool processingExecutor,
-                            final SchemaRepositoryProvider schemaRepositoryProvider,
+                            final SchemaResourceManager schemaRepositoryProvider,
                             final DataBroker dataBroker, final DOMMountPointService mountPointService,
                             final AAAEncryptionService encryptionService,
                             final DeviceActionFactory deviceActionFactory) {
                             final DataBroker dataBroker, final DOMMountPointService mountPointService,
                             final AAAEncryptionService encryptionService,
                             final DeviceActionFactory deviceActionFactory) {
index d4cd6195a30b43a7f98ab14c084e4752465f1915..c3a6c2dfd191dd347c8636a4aa7b28a6d63547d8 100644 (file)
                interface="org.opendaylight.aaa.encrypt.AAAEncryptionService" />
     <reference id="deviceActionFactory"
                interface="org.opendaylight.netconf.sal.connect.api.DeviceActionFactory"/>
                interface="org.opendaylight.aaa.encrypt.AAAEncryptionService" />
     <reference id="deviceActionFactory"
                interface="org.opendaylight.netconf.sal.connect.api.DeviceActionFactory"/>
-
-    <bean id="schemaRepository" class="org.opendaylight.netconf.topology.spi.SharedSchemaRepositoryProvider">
-        <argument value="callhome-topology-schemas"/>
-    </bean>
+    <reference id="schemaManager"
+               interface="org.opendaylight.netconf.sal.connect.api.SchemaResourceManager"/>
 
     <bean id="callhomeProvider" class="org.opendaylight.netconf.callhome.mount.IetfZeroTouchCallHomeServerProvider"
           init-method="init"
 
     <bean id="callhomeProvider" class="org.opendaylight.netconf.callhome.mount.IetfZeroTouchCallHomeServerProvider"
           init-method="init"
@@ -45,7 +43,7 @@
         <argument ref="eventExecutor"/>
         <argument ref="keepAliveExecutor"/>
         <argument ref="processingExecutor"/>
         <argument ref="eventExecutor"/>
         <argument ref="keepAliveExecutor"/>
         <argument ref="processingExecutor"/>
-        <argument ref="schemaRepository"/>
+        <argument ref="schemaManager"/>
         <argument ref="dataBroker"/>
         <argument ref="domMountPointService"/>
         <argument ref="encryptionService"/>
         <argument ref="dataBroker"/>
         <argument ref="domMountPointService"/>
         <argument ref="encryptionService"/>
index ecac3cc607db4b666054d4396539ab4d65ff636c..d2037dcf33bb3933350973c919867b6403ceeeba 100644 (file)
@@ -35,7 +35,7 @@ import org.opendaylight.netconf.client.conf.NetconfClientConfiguration;
 import org.opendaylight.netconf.client.conf.NetconfClientConfigurationBuilder;
 import org.opendaylight.netconf.nettyutil.ReconnectStrategy;
 import org.opendaylight.netconf.nettyutil.handler.ssh.authentication.AuthenticationHandler;
 import org.opendaylight.netconf.client.conf.NetconfClientConfigurationBuilder;
 import org.opendaylight.netconf.nettyutil.ReconnectStrategy;
 import org.opendaylight.netconf.nettyutil.handler.ssh.authentication.AuthenticationHandler;
-import org.opendaylight.netconf.topology.api.SchemaRepositoryProvider;
+import org.opendaylight.netconf.sal.connect.api.SchemaResourceManager;
 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
 
 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
 
@@ -44,7 +44,7 @@ public class CallHomeMountDispatcherTest {
     private EventExecutor mockExecutor;
     private ScheduledThreadPool mockKeepAlive;
     private ThreadPool mockProcessingExecutor;
     private EventExecutor mockExecutor;
     private ScheduledThreadPool mockKeepAlive;
     private ThreadPool mockProcessingExecutor;
-    private SchemaRepositoryProvider mockSchemaRepoProvider;
+    private SchemaResourceManager mockSchemaRepoProvider;
 
     private CallHomeMountDispatcher instance;
     private DataBroker mockDataBroker;
 
     private CallHomeMountDispatcher instance;
     private DataBroker mockDataBroker;
@@ -61,7 +61,7 @@ public class CallHomeMountDispatcherTest {
         mockExecutor = mock(EventExecutor.class);
         mockKeepAlive = mock(ScheduledThreadPool.class);
         mockProcessingExecutor = mock(ThreadPool.class);
         mockExecutor = mock(EventExecutor.class);
         mockKeepAlive = mock(ScheduledThreadPool.class);
         mockProcessingExecutor = mock(ThreadPool.class);
-        mockSchemaRepoProvider = mock(SchemaRepositoryProvider.class);
+        mockSchemaRepoProvider = mock(SchemaResourceManager.class);
         mockDataBroker = mock(DataBroker.class);
         mockMount = mock(DOMMountPointService.class);
         mockSessMgr = mock(CallHomeMountSessionManager.class);
         mockDataBroker = mock(DataBroker.class);
         mockMount = mock(DOMMountPointService.class);
         mockSessMgr = mock(CallHomeMountSessionManager.class);
index dc17c5105de0939e1eb3c0b971343a16984c765f..1a3a443b2317f1a9575b26dfc00f160359f1c33b 100644 (file)
@@ -27,10 +27,10 @@ import org.opendaylight.mdsal.dom.api.DOMMountPointService;
 import org.opendaylight.netconf.client.NetconfClientDispatcher;
 import org.opendaylight.netconf.sal.connect.api.DeviceActionFactory;
 import org.opendaylight.netconf.sal.connect.api.RemoteDeviceHandler;
 import org.opendaylight.netconf.client.NetconfClientDispatcher;
 import org.opendaylight.netconf.sal.connect.api.DeviceActionFactory;
 import org.opendaylight.netconf.sal.connect.api.RemoteDeviceHandler;
+import org.opendaylight.netconf.sal.connect.api.SchemaResourceManager;
 import org.opendaylight.netconf.sal.connect.netconf.listener.NetconfSessionPreferences;
 import org.opendaylight.netconf.sal.connect.netconf.sal.NetconfDeviceSalFacade;
 import org.opendaylight.netconf.sal.connect.util.RemoteDeviceId;
 import org.opendaylight.netconf.sal.connect.netconf.listener.NetconfSessionPreferences;
 import org.opendaylight.netconf.sal.connect.netconf.sal.NetconfDeviceSalFacade;
 import org.opendaylight.netconf.sal.connect.util.RemoteDeviceId;
-import org.opendaylight.netconf.topology.api.SchemaRepositoryProvider;
 import org.opendaylight.netconf.topology.spi.AbstractNetconfTopology;
 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.NetworkTopologyBuilder;
 import org.opendaylight.netconf.topology.spi.AbstractNetconfTopology;
 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.NetworkTopologyBuilder;
@@ -58,7 +58,7 @@ public class NetconfTopologyImpl extends AbstractNetconfTopology
     public NetconfTopologyImpl(final String topologyId, final NetconfClientDispatcher clientDispatcher,
             final EventExecutor eventExecutor, final ScheduledThreadPool keepaliveExecutor,
             final ThreadPool processingExecutor,
     public NetconfTopologyImpl(final String topologyId, final NetconfClientDispatcher clientDispatcher,
             final EventExecutor eventExecutor, final ScheduledThreadPool keepaliveExecutor,
             final ThreadPool processingExecutor,
-            final SchemaRepositoryProvider schemaRepositoryProvider,
+            final SchemaResourceManager schemaRepositoryProvider,
             final DataBroker dataBroker, final DOMMountPointService mountPointService,
             final AAAEncryptionService encryptionService) {
         this(topologyId, clientDispatcher, eventExecutor, keepaliveExecutor, processingExecutor,
             final DataBroker dataBroker, final DOMMountPointService mountPointService,
             final AAAEncryptionService encryptionService) {
         this(topologyId, clientDispatcher, eventExecutor, keepaliveExecutor, processingExecutor,
@@ -68,7 +68,7 @@ public class NetconfTopologyImpl extends AbstractNetconfTopology
     public NetconfTopologyImpl(final String topologyId, final NetconfClientDispatcher clientDispatcher,
             final EventExecutor eventExecutor, final ScheduledThreadPool keepaliveExecutor,
             final ThreadPool processingExecutor,
     public NetconfTopologyImpl(final String topologyId, final NetconfClientDispatcher clientDispatcher,
             final EventExecutor eventExecutor, final ScheduledThreadPool keepaliveExecutor,
             final ThreadPool processingExecutor,
-            final SchemaRepositoryProvider schemaRepositoryProvider,
+            final SchemaResourceManager schemaRepositoryProvider,
             final DataBroker dataBroker, final DOMMountPointService mountPointService,
             final AAAEncryptionService encryptionService,
             final DeviceActionFactory deviceActionFactory) {
             final DataBroker dataBroker, final DOMMountPointService mountPointService,
             final AAAEncryptionService encryptionService,
             final DeviceActionFactory deviceActionFactory) {
index e95c26948a8b40d39d0e81d398ae9e0ceae812fe..06b7c198994f65b5bda15810fd74b7d77132b9c2 100644 (file)
                interface="org.opendaylight.aaa.encrypt.AAAEncryptionService" />
     <reference id="deviceActionFactory"
                interface="org.opendaylight.netconf.sal.connect.api.DeviceActionFactory"/>
                interface="org.opendaylight.aaa.encrypt.AAAEncryptionService" />
     <reference id="deviceActionFactory"
                interface="org.opendaylight.netconf.sal.connect.api.DeviceActionFactory"/>
-
-    <bean id="schemaRepository" class="org.opendaylight.netconf.topology.spi.SharedSchemaRepositoryProvider">
-        <argument value="netconf-topology-schemas"/>
-    </bean>
+    <reference id="schemaManager"
+               interface="org.opendaylight.netconf.sal.connect.api.SchemaResourceManager"/>
 
     <cm:property-placeholder persistent-id="org.opendaylight.netconf.topology.sb.keypair" update-strategy="none">
       <cm:default-properties>
 
     <cm:property-placeholder persistent-id="org.opendaylight.netconf.topology.sb.keypair" update-strategy="none">
       <cm:default-properties>
@@ -54,7 +52,7 @@
         <argument ref="eventExecutor"/>
         <argument ref="keepAliveExecutor"/>
         <argument ref="processingExecutor"/>
         <argument ref="eventExecutor"/>
         <argument ref="keepAliveExecutor"/>
         <argument ref="processingExecutor"/>
-        <argument ref="schemaRepository"/>
+        <argument ref="schemaManager"/>
         <argument ref="dataBroker"/>
         <argument ref="mountPointService"/>
         <property name="privateKeyPath" value="${private-key-path}"/>
         <argument ref="dataBroker"/>
         <argument ref="mountPointService"/>
         <property name="privateKeyPath" value="${private-key-path}"/>
index 372dc443eae5b1542720fae3d48d6f9ed83819e5..96a6696152e300979b6e325342bebce676d2dc0f 100644 (file)
@@ -21,16 +21,14 @@ import com.google.common.util.concurrent.Futures;
 import com.google.common.util.concurrent.ListenableFuture;
 import com.google.common.util.concurrent.MoreExecutors;
 import io.netty.util.concurrent.EventExecutor;
 import com.google.common.util.concurrent.ListenableFuture;
 import com.google.common.util.concurrent.MoreExecutors;
 import io.netty.util.concurrent.EventExecutor;
-import io.netty.util.concurrent.Future;
-import io.netty.util.concurrent.ImmediateEventExecutor;
-import io.netty.util.concurrent.SucceededFuture;
 import java.util.Collection;
 import java.util.HashSet;
 import org.junit.Assert;
 import org.junit.Before;
 import org.junit.Test;
 import java.util.Collection;
 import java.util.HashSet;
 import org.junit.Assert;
 import org.junit.Before;
 import org.junit.Test;
+import org.junit.runner.RunWith;
 import org.mockito.Mock;
 import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
+import org.mockito.junit.MockitoJUnitRunner;
 import org.opendaylight.aaa.encrypt.AAAEncryptionService;
 import org.opendaylight.controller.config.threadpool.ScheduledThreadPool;
 import org.opendaylight.controller.config.threadpool.ThreadPool;
 import org.opendaylight.aaa.encrypt.AAAEncryptionService;
 import org.opendaylight.controller.config.threadpool.ScheduledThreadPool;
 import org.opendaylight.controller.config.threadpool.ThreadPool;
@@ -44,8 +42,8 @@ import org.opendaylight.netconf.client.NetconfClientDispatcher;
 import org.opendaylight.netconf.client.NetconfClientSessionListener;
 import org.opendaylight.netconf.client.conf.NetconfClientConfiguration;
 import org.opendaylight.netconf.client.conf.NetconfReconnectingClientConfiguration;
 import org.opendaylight.netconf.client.NetconfClientSessionListener;
 import org.opendaylight.netconf.client.conf.NetconfClientConfiguration;
 import org.opendaylight.netconf.client.conf.NetconfReconnectingClientConfiguration;
+import org.opendaylight.netconf.sal.connect.api.SchemaResourceManager;
 import org.opendaylight.netconf.sal.connect.netconf.listener.NetconfDeviceCapabilities;
 import org.opendaylight.netconf.sal.connect.netconf.listener.NetconfDeviceCapabilities;
-import org.opendaylight.netconf.topology.api.SchemaRepositoryProvider;
 import org.opendaylight.netconf.topology.spi.AbstractNetconfTopology;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Host;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
 import org.opendaylight.netconf.topology.spi.AbstractNetconfTopology;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Host;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
@@ -68,10 +66,12 @@ import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.
 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.NodeKey;
 import org.opendaylight.yangtools.yang.binding.DataObject;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.NodeKey;
 import org.opendaylight.yangtools.yang.binding.DataObject;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.IdentifiableItem;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.PathArgument;
 import org.opendaylight.yangtools.yang.common.Uint16;
 import org.opendaylight.yangtools.yang.common.Uint32;
 import org.opendaylight.yangtools.yang.common.Uint16;
 import org.opendaylight.yangtools.yang.common.Uint32;
-import org.opendaylight.yangtools.yang.parser.repo.SharedSchemaRepository;
 
 
+@RunWith(MockitoJUnitRunner.StrictStubs.class)
 public class NetconfTopologyImplTest {
 
     private static final NodeId NODE_ID = new NodeId("testing-node");
 public class NetconfTopologyImplTest {
 
     private static final NodeId NODE_ID = new NodeId("testing-node");
@@ -90,7 +90,7 @@ public class NetconfTopologyImplTest {
     private ThreadPool mockedProcessingExecutor;
 
     @Mock
     private ThreadPool mockedProcessingExecutor;
 
     @Mock
-    private SchemaRepositoryProvider mockedSchemaRepositoryProvider;
+    private SchemaResourceManager mockedResourceManager;
 
     @Mock
     private DataBroker dataBroker;
 
     @Mock
     private DataBroker dataBroker;
@@ -106,18 +106,11 @@ public class NetconfTopologyImplTest {
 
     @Before
     public void setUp() {
 
     @Before
     public void setUp() {
-        MockitoAnnotations.initMocks(this);
-
-        when(mockedSchemaRepositoryProvider.getSharedSchemaRepository())
-                .thenReturn(new SharedSchemaRepository("testingSharedSchemaRepo"));
         when(mockedProcessingExecutor.getExecutor()).thenReturn(MoreExecutors.newDirectExecutorService());
         when(mockedProcessingExecutor.getExecutor()).thenReturn(MoreExecutors.newDirectExecutorService());
-        final Future future = new SucceededFuture(ImmediateEventExecutor.INSTANCE, new NetconfDeviceCapabilities());
-        when(mockedClientDispatcher.createReconnectingClient(any(NetconfReconnectingClientConfiguration.class)))
-                .thenReturn(future);
 
 
-        topology = new TestingNetconfTopologyImpl(TOPOLOGY_ID, mockedClientDispatcher,
-                mockedEventExecutor, mockedKeepaliveExecutor, mockedProcessingExecutor, mockedSchemaRepositoryProvider,
-                dataBroker, mountPointService, encryptionService);
+        topology = new TestingNetconfTopologyImpl(TOPOLOGY_ID, mockedClientDispatcher, mockedEventExecutor,
+            mockedKeepaliveExecutor, mockedProcessingExecutor, mockedResourceManager, dataBroker, mountPointService,
+            encryptionService);
 
         spyTopology = spy(topology);
     }
 
         spyTopology = spy(topology);
     }
@@ -150,14 +143,7 @@ public class NetconfTopologyImplTest {
         final DataObjectModification<Node> newNode = mock(DataObjectModification.class);
         when(newNode.getModificationType()).thenReturn(DataObjectModification.ModificationType.WRITE);
 
         final DataObjectModification<Node> newNode = mock(DataObjectModification.class);
         when(newNode.getModificationType()).thenReturn(DataObjectModification.ModificationType.WRITE);
 
-        InstanceIdentifier.PathArgument pa = null;
-
-        for (final InstanceIdentifier.PathArgument p
-                : NetconfTopologyImpl.createTopologyListPath(TOPOLOGY_ID)
-                    .child(Node.class, new NodeKey(NODE_ID)).getPathArguments()) {
-            pa = p;
-        }
-
+        PathArgument pa = IdentifiableItem.of(Node.class, new NodeKey(NODE_ID));
         when(newNode.getIdentifier()).thenReturn(pa);
 
 
         when(newNode.getIdentifier()).thenReturn(pa);
 
 
@@ -283,7 +269,7 @@ public class NetconfTopologyImplTest {
                                           final EventExecutor eventExecutor,
                                           final ScheduledThreadPool keepaliveExecutor,
                                           final ThreadPool processingExecutor,
                                           final EventExecutor eventExecutor,
                                           final ScheduledThreadPool keepaliveExecutor,
                                           final ThreadPool processingExecutor,
-                                          final SchemaRepositoryProvider schemaRepositoryProvider,
+                                          final SchemaResourceManager schemaRepositoryProvider,
                                           final DataBroker dataBroker, final DOMMountPointService mountPointService,
                                           final AAAEncryptionService encryptionService) {
             super(topologyId, clientDispatcher, eventExecutor, keepaliveExecutor,
                                           final DataBroker dataBroker, final DOMMountPointService mountPointService,
                                           final AAAEncryptionService encryptionService) {
             super(topologyId, clientDispatcher, eventExecutor, keepaliveExecutor,
index c36d69acfcb7ffd6383d313b6ffac1d49f658ba3..ce4f0868b5a6fd1a3d435293aa04e60d79158fb7 100644 (file)
@@ -41,6 +41,8 @@ import org.opendaylight.mdsal.singleton.common.api.ClusterSingletonServiceRegist
 import org.opendaylight.mdsal.singleton.common.api.ServiceGroupIdentifier;
 import org.opendaylight.netconf.client.NetconfClientDispatcher;
 import org.opendaylight.netconf.sal.connect.api.DeviceActionFactory;
 import org.opendaylight.mdsal.singleton.common.api.ServiceGroupIdentifier;
 import org.opendaylight.netconf.client.NetconfClientDispatcher;
 import org.opendaylight.netconf.sal.connect.api.DeviceActionFactory;
+import org.opendaylight.netconf.sal.connect.api.SchemaResourceManager;
+import org.opendaylight.netconf.sal.connect.util.RemoteDeviceId;
 import org.opendaylight.netconf.topology.singleton.api.NetconfTopologySingletonService;
 import org.opendaylight.netconf.topology.singleton.impl.utils.NetconfTopologySetup;
 import org.opendaylight.netconf.topology.singleton.impl.utils.NetconfTopologySetup.NetconfTopologySetupBuilder;
 import org.opendaylight.netconf.topology.singleton.api.NetconfTopologySingletonService;
 import org.opendaylight.netconf.topology.singleton.impl.utils.NetconfTopologySetup;
 import org.opendaylight.netconf.topology.singleton.impl.utils.NetconfTopologySetup.NetconfTopologySetupBuilder;
@@ -84,6 +86,7 @@ public class NetconfTopologyManager
     private final DOMMountPointService mountPointService;
     private final AAAEncryptionService encryptionService;
     private final DeviceActionFactory deviceActionFactory;
     private final DOMMountPointService mountPointService;
     private final AAAEncryptionService encryptionService;
     private final DeviceActionFactory deviceActionFactory;
+    private final SchemaResourceManager resourceManager;
     private ListenerRegistration<NetconfTopologyManager> dataChangeListenerRegistration;
     private String privateKeyPath;
     private String privateKeyPassphrase;
     private ListenerRegistration<NetconfTopologyManager> dataChangeListenerRegistration;
     private String privateKeyPath;
     private String privateKeyPassphrase;
@@ -97,8 +100,8 @@ public class NetconfTopologyManager
                                   final String topologyId, final Config config,
                                   final DOMMountPointService mountPointService,
                                   final AAAEncryptionService encryptionService,
                                   final String topologyId, final Config config,
                                   final DOMMountPointService mountPointService,
                                   final AAAEncryptionService encryptionService,
-                                  final DeviceActionFactory deviceActionFactory) {
-
+                                  final DeviceActionFactory deviceActionFactory,
+                                  final SchemaResourceManager resourceManager) {
         this.dataBroker = requireNonNull(dataBroker);
         this.rpcProviderRegistry = requireNonNull(rpcProviderRegistry);
         this.actionProviderRegistry = requireNonNull(actionProviderService);
         this.dataBroker = requireNonNull(dataBroker);
         this.rpcProviderRegistry = requireNonNull(rpcProviderRegistry);
         this.actionProviderRegistry = requireNonNull(actionProviderService);
@@ -113,7 +116,7 @@ public class NetconfTopologyManager
         this.mountPointService = mountPointService;
         this.encryptionService = requireNonNull(encryptionService);
         this.deviceActionFactory = requireNonNull(deviceActionFactory);
         this.mountPointService = mountPointService;
         this.encryptionService = requireNonNull(encryptionService);
         this.deviceActionFactory = requireNonNull(deviceActionFactory);
-
+        this.resourceManager = requireNonNull(resourceManager);
     }
 
     // Blueprint init method
     }
 
     // Blueprint init method
@@ -282,6 +285,9 @@ public class NetconfTopologyManager
     }
 
     private NetconfTopologySetup createSetup(final InstanceIdentifier<Node> instanceIdentifier, final Node node) {
     }
 
     private NetconfTopologySetup createSetup(final InstanceIdentifier<Node> instanceIdentifier, final Node node) {
+        final NetconfNode netconfNode = node.augmentation(NetconfNode.class);
+        final RemoteDeviceId deviceId = NetconfTopologyUtils.createRemoteDeviceId(node.getNodeId(), netconfNode);
+
         final NetconfTopologySetupBuilder builder = NetconfTopologySetupBuilder.create()
                 .setClusterSingletonServiceProvider(clusterSingletonServiceProvider)
                 .setDataBroker(dataBroker)
         final NetconfTopologySetupBuilder builder = NetconfTopologySetupBuilder.create()
                 .setClusterSingletonServiceProvider(clusterSingletonServiceProvider)
                 .setDataBroker(dataBroker)
@@ -295,7 +301,7 @@ public class NetconfTopologyManager
                 .setProcessingExecutor(processingExecutor)
                 .setTopologyId(topologyId)
                 .setNetconfClientDispatcher(clientDispatcher)
                 .setProcessingExecutor(processingExecutor)
                 .setTopologyId(topologyId)
                 .setNetconfClientDispatcher(clientDispatcher)
-                .setSchemaResourceDTO(NetconfTopologyUtils.setupSchemaCacheDTO(node))
+                .setSchemaResourceDTO(resourceManager.getSchemaResources(netconfNode, deviceId))
                 .setIdleTimeout(writeTxIdleTimeout)
                 .setPrivateKeyPath(privateKeyPath)
                 .setPrivateKeyPassphrase(privateKeyPassphrase)
                 .setIdleTimeout(writeTxIdleTimeout)
                 .setPrivateKeyPath(privateKeyPath)
                 .setPrivateKeyPassphrase(privateKeyPassphrase)
index 022005d6f5612304d5c636dd39d21d06a19f4175..a005f53d249659ad2482c094b8ce656e1026835c 100644 (file)
@@ -8,17 +8,9 @@
 
 package org.opendaylight.netconf.topology.singleton.impl.utils;
 
 
 package org.opendaylight.netconf.topology.singleton.impl.utils;
 
-import com.google.common.base.Strings;
-import com.google.common.util.concurrent.Uninterruptibles;
-import java.io.File;
 import java.math.BigDecimal;
 import java.net.InetSocketAddress;
 import java.math.BigDecimal;
 import java.net.InetSocketAddress;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.concurrent.TimeUnit;
 import org.opendaylight.netconf.api.DocumentedException;
 import org.opendaylight.netconf.api.DocumentedException;
-import org.opendaylight.netconf.sal.connect.netconf.NetconfDevice;
-import org.opendaylight.netconf.sal.connect.netconf.NetconfStateSchemasResolverImpl;
 import org.opendaylight.netconf.sal.connect.util.RemoteDeviceId;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.NetconfNode;
 import org.opendaylight.netconf.sal.connect.util.RemoteDeviceId;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.NetconfNode;
@@ -32,23 +24,12 @@ import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.
 import org.opendaylight.yangtools.yang.binding.Identifier;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 import org.opendaylight.yangtools.yang.binding.KeyedInstanceIdentifier;
 import org.opendaylight.yangtools.yang.binding.Identifier;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 import org.opendaylight.yangtools.yang.binding.KeyedInstanceIdentifier;
-import org.opendaylight.yangtools.yang.model.repo.api.EffectiveModelContextFactory;
-import org.opendaylight.yangtools.yang.model.repo.api.SchemaRepository;
-import org.opendaylight.yangtools.yang.model.repo.api.YangTextSchemaSource;
-import org.opendaylight.yangtools.yang.model.repo.spi.SchemaSourceRegistry;
-import org.opendaylight.yangtools.yang.model.repo.util.FilesystemSchemaSourceCache;
-import org.opendaylight.yangtools.yang.model.repo.util.InMemorySchemaSourceCache;
-import org.opendaylight.yangtools.yang.parser.repo.SharedSchemaRepository;
-import org.opendaylight.yangtools.yang.parser.rfc7950.repo.ASTSchemaSource;
-import org.opendaylight.yangtools.yang.parser.rfc7950.repo.TextToASTTransformer;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 public final class NetconfTopologyUtils {
     private static final Logger LOG = LoggerFactory.getLogger(NetconfTopologyUtils.class);
 
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 public final class NetconfTopologyUtils {
     private static final Logger LOG = LoggerFactory.getLogger(NetconfTopologyUtils.class);
 
-    private static final String DEFAULT_SCHEMA_REPOSITORY_NAME = "sal-netconf-connector";
-
     public static final long DEFAULT_REQUEST_TIMEOUT_MILLIS = 60000L;
     public static final int DEFAULT_KEEPALIVE_DELAY = 0;
     public static final boolean DEFAULT_RECONNECT_ON_CHANGED_SCHEMA = false;
     public static final long DEFAULT_REQUEST_TIMEOUT_MILLIS = 60000L;
     public static final int DEFAULT_KEEPALIVE_DELAY = 0;
     public static final boolean DEFAULT_RECONNECT_ON_CHANGED_SCHEMA = false;
@@ -59,157 +40,10 @@ public final class NetconfTopologyUtils {
     public static final long DEFAULT_CONNECTION_TIMEOUT_MILLIS = 20000L;
     public static final BigDecimal DEFAULT_SLEEP_FACTOR = new BigDecimal(1.5);
 
     public static final long DEFAULT_CONNECTION_TIMEOUT_MILLIS = 20000L;
     public static final BigDecimal DEFAULT_SLEEP_FACTOR = new BigDecimal(1.5);
 
-
-    // The default cache directory relative to <code>CACHE_DIRECTORY</code>
-
-    public static final String DEFAULT_CACHE_DIRECTORY = "schema";
-
-    // Filesystem based caches are stored relative to the cache directory.
-    public static final String CACHE_DIRECTORY = "cache";
-
-    // The qualified schema cache directory <code>cache/schema</code>
-    public static final String QUALIFIED_DEFAULT_CACHE_DIRECTORY =
-            CACHE_DIRECTORY + File.separator + DEFAULT_CACHE_DIRECTORY;
-
-    // The default schema repository in the case that one is not specified.
-    public static final SharedSchemaRepository DEFAULT_SCHEMA_REPOSITORY =
-            new SharedSchemaRepository(DEFAULT_SCHEMA_REPOSITORY_NAME);
-
-    public static final InMemorySchemaSourceCache<ASTSchemaSource> DEFAULT_AST_CACHE =
-            InMemorySchemaSourceCache.createSoftCache(DEFAULT_SCHEMA_REPOSITORY, ASTSchemaSource.class);
-
-    // The default factory for creating <code>SchemaContext</code> instances.
-    public static final EffectiveModelContextFactory DEFAULT_SCHEMA_CONTEXT_FACTORY =
-            DEFAULT_SCHEMA_REPOSITORY.createEffectiveModelContextFactory();
-
-    /**
-     * Keeps track of initialized Schema resources.  A Map is maintained in which the key represents the name
-     * of the schema cache directory, and the value is a corresponding <code>SchemaResourcesDTO</code>.  The
-     * <code>SchemaResourcesDTO</code> is essentially a container that allows for the extraction of the
-     * <code>SchemaRegistry</code> and <code>SchemaContextFactory</code> which should be used for a particular
-     * Netconf mount.  Access to <code>SCHEMA_RESOURCES_DTO_MAP</code> should be surrounded by appropriate
-     * synchronization locks.
-     */
-    private static final Map<String, NetconfDevice.SchemaResourcesDTO> SCHEMA_RESOURCES_DTO_MAP = new HashMap<>();
-
-    // Initializes default constant instances for the case when the default schema repository
-    // directory cache/schema is used.
-    static {
-        SCHEMA_RESOURCES_DTO_MAP.put(DEFAULT_CACHE_DIRECTORY,
-                new NetconfDevice.SchemaResourcesDTO(DEFAULT_SCHEMA_REPOSITORY, DEFAULT_SCHEMA_REPOSITORY,
-                        DEFAULT_SCHEMA_CONTEXT_FACTORY, new NetconfStateSchemasResolverImpl()));
-        DEFAULT_SCHEMA_REPOSITORY.registerSchemaSourceListener(DEFAULT_AST_CACHE);
-        DEFAULT_SCHEMA_REPOSITORY.registerSchemaSourceListener(
-                TextToASTTransformer.create(DEFAULT_SCHEMA_REPOSITORY, DEFAULT_SCHEMA_REPOSITORY));
-
-        /*
-         * Create the default <code>FilesystemSchemaSourceCache</code>, which stores cached files
-         * in <code>cache/schema</code>. Try up to 3 times - we've seen intermittent failures on jenkins where
-         * FilesystemSchemaSourceCache throws an IAE due to mkdirs failure. The theory is that there's a race
-         * creating the dir and it already exists when mkdirs is called (mkdirs returns false in this case). In this
-         * scenario, a retry should succeed.
-         */
-        int tries = 1;
-        while (true) {
-            try {
-                FilesystemSchemaSourceCache<YangTextSchemaSource> defaultCache =
-                        new FilesystemSchemaSourceCache<>(DEFAULT_SCHEMA_REPOSITORY, YangTextSchemaSource.class,
-                                new File(QUALIFIED_DEFAULT_CACHE_DIRECTORY));
-                DEFAULT_SCHEMA_REPOSITORY.registerSchemaSourceListener(defaultCache);
-                break;
-            } catch (IllegalArgumentException e) {
-                if (tries++ >= 3) {
-                    LOG.error("Error creating default schema cache", e);
-                    break;
-                }
-                Uninterruptibles.sleepUninterruptibly(100, TimeUnit.MILLISECONDS);
-            }
-        }
-    }
-
     private NetconfTopologyUtils() {
 
     }
 
     private NetconfTopologyUtils() {
 
     }
 
-    public static NetconfDevice.SchemaResourcesDTO setupSchemaCacheDTO(final Node node) {
-        final NetconfNode netconfNode = node.augmentation(NetconfNode.class);
-        final String moduleSchemaCacheDirectory = netconfNode.getSchemaCacheDirectory();
-        final RemoteDeviceId deviceId = createRemoteDeviceId(node.getNodeId(), netconfNode);
-
-        // Setup information related to the SchemaRegistry, SchemaResourceFactory, etc.
-        NetconfDevice.SchemaResourcesDTO schemaResourcesDTO = null;
-        // Only checks to ensure the String is not empty or null;  further checks related to directory accessibility
-        // and file permissions are handled during the FilesystemSchemaSourceCache initialization.
-        if (!Strings.isNullOrEmpty(moduleSchemaCacheDirectory)) {
-            // If a custom schema cache directory is specified, create the backing DTO; otherwise, the SchemaRegistry
-            // and SchemaContextFactory remain the default values.
-            if (!moduleSchemaCacheDirectory.equals(DEFAULT_CACHE_DIRECTORY)) {
-                // Multiple modules may be created at once;  synchronize to avoid issues with data consistency among
-                // threads.
-                synchronized (SCHEMA_RESOURCES_DTO_MAP) {
-                    // Look for the cached DTO to reuse SchemaRegistry and SchemaContextFactory variables if
-                    // they already exist
-                    schemaResourcesDTO = SCHEMA_RESOURCES_DTO_MAP.get(moduleSchemaCacheDirectory);
-                    if (schemaResourcesDTO == null) {
-                        schemaResourcesDTO = createSchemaResourcesDTO(moduleSchemaCacheDirectory);
-                        schemaResourcesDTO.getSchemaRegistry().registerSchemaSourceListener(
-                                TextToASTTransformer.create((SchemaRepository) schemaResourcesDTO.getSchemaRegistry(),
-                                        schemaResourcesDTO.getSchemaRegistry())
-                        );
-                        SCHEMA_RESOURCES_DTO_MAP.put(moduleSchemaCacheDirectory, schemaResourcesDTO);
-                    }
-                }
-                LOG.info("{} : netconf connector will use schema cache directory {} instead of {}",
-                        deviceId, moduleSchemaCacheDirectory, DEFAULT_CACHE_DIRECTORY);
-            }
-        }
-
-        if (schemaResourcesDTO == null) {
-            synchronized (SCHEMA_RESOURCES_DTO_MAP) {
-                schemaResourcesDTO = SCHEMA_RESOURCES_DTO_MAP.get(DEFAULT_CACHE_DIRECTORY);
-            }
-            LOG.info("{} : using the default directory {}",
-                    deviceId, QUALIFIED_DEFAULT_CACHE_DIRECTORY);
-        }
-
-        return schemaResourcesDTO;
-    }
-
-    /**
-     * Creates the backing Schema classes for a particular directory.
-     *
-     * @param moduleSchemaCacheDirectory The string directory relative to "cache"
-     * @return A DTO containing the Schema classes for the Netconf mount.
-     */
-    private static NetconfDevice.SchemaResourcesDTO createSchemaResourcesDTO(final String moduleSchemaCacheDirectory) {
-        final SharedSchemaRepository repository = new SharedSchemaRepository(moduleSchemaCacheDirectory);
-        final EffectiveModelContextFactory schemaContextFactory
-                = repository.createEffectiveModelContextFactory();
-
-        final FilesystemSchemaSourceCache<YangTextSchemaSource> deviceCache =
-                createDeviceFilesystemCache(moduleSchemaCacheDirectory, repository);
-        repository.registerSchemaSourceListener(deviceCache);
-        repository.registerSchemaSourceListener(InMemorySchemaSourceCache.createSoftCache(repository,
-                ASTSchemaSource.class));
-        return new NetconfDevice.SchemaResourcesDTO(repository, repository, schemaContextFactory,
-                new NetconfStateSchemasResolverImpl());
-    }
-
-    /**
-     * Creates a <code>FilesystemSchemaSourceCache</code> for the custom schema cache directory.
-     *
-     * @param schemaCacheDirectory The custom cache directory relative to "cache"
-     * @return A <code>FilesystemSchemaSourceCache</code> for the custom schema cache directory
-     */
-    private static FilesystemSchemaSourceCache<YangTextSchemaSource> createDeviceFilesystemCache(
-            final String schemaCacheDirectory, final SchemaSourceRegistry schemaRegistry) {
-        final String relativeSchemaCacheDirectory =
-                NetconfTopologyUtils.CACHE_DIRECTORY + File.separator + schemaCacheDirectory;
-        return new FilesystemSchemaSourceCache<>(schemaRegistry, YangTextSchemaSource.class,
-                new File(relativeSchemaCacheDirectory));
-    }
-
-
     public static RemoteDeviceId createRemoteDeviceId(final NodeId nodeId, final NetconfNode node) {
         final IpAddress ipAddress = node.getHost().getIpAddress();
         final InetSocketAddress address = new InetSocketAddress(ipAddress.getIpv4Address() != null
     public static RemoteDeviceId createRemoteDeviceId(final NodeId nodeId, final NetconfNode node) {
         final IpAddress ipAddress = node.getHost().getIpAddress();
         final InetSocketAddress address = new InetSocketAddress(ipAddress.getIpv4Address() != null
index 91ef4f842b33c4b8d23ee731381c8f8ce01fa1c9..b2e2e59dd0ae0ea2536d3f8126eb0e824330a3b1 100644 (file)
@@ -39,6 +39,8 @@ and is available at http://www.eclipse.org/legal/epl-v10.html
                odl:type="default"/>
     <reference id="deviceActionFactory"
                interface="org.opendaylight.netconf.sal.connect.api.DeviceActionFactory"/>
                odl:type="default"/>
     <reference id="deviceActionFactory"
                interface="org.opendaylight.netconf.sal.connect.api.DeviceActionFactory"/>
+    <reference id="schemaManager"
+               interface="org.opendaylight.netconf.sal.connect.api.SchemaResourceManager"/>
     <odl:clustered-app-config
             id="singletonConfig"
             binding-class="org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.topology.singleton.config.rev170419.Config"
     <odl:clustered-app-config
             id="singletonConfig"
             binding-class="org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.topology.singleton.config.rev170419.Config"
@@ -75,6 +77,7 @@ and is available at http://www.eclipse.org/legal/epl-v10.html
         <property name="privateKeyPassphrase" value="${private-key-passphrase}"/>
         <argument ref="encryptionService" />
         <argument ref="deviceActionFactory"/>
         <property name="privateKeyPassphrase" value="${private-key-passphrase}"/>
         <argument ref="encryptionService" />
         <argument ref="deviceActionFactory"/>
+        <argument ref="schemaManager"/>
     </bean>
     <service ref="netconfTopologyManager"
              interface="org.opendaylight.netconf.topology.singleton.api.NetconfTopologySingletonService"/>
     </bean>
     <service ref="netconfTopologyManager"
              interface="org.opendaylight.netconf.topology.singleton.api.NetconfTopologySingletonService"/>
index 638de1831b4c26935527022b409a5055f69214db..9ff232a71b545d0828018b6ee927bc42e24eb014 100644 (file)
@@ -21,7 +21,6 @@ import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.timeout;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.timeout;
 import static org.mockito.Mockito.verify;
-import static org.mockito.MockitoAnnotations.initMocks;
 
 import akka.actor.ActorSystem;
 import akka.testkit.javadsl.TestKit;
 
 import akka.actor.ActorSystem;
 import akka.testkit.javadsl.TestKit;
@@ -52,7 +51,9 @@ import org.apache.commons.io.FileUtils;
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
+import org.junit.runner.RunWith;
 import org.mockito.Mock;
 import org.mockito.Mock;
+import org.mockito.junit.MockitoJUnitRunner;
 import org.opendaylight.aaa.encrypt.AAAEncryptionService;
 import org.opendaylight.controller.cluster.ActorSystemProvider;
 import org.opendaylight.controller.config.threadpool.ScheduledThreadPool;
 import org.opendaylight.aaa.encrypt.AAAEncryptionService;
 import org.opendaylight.controller.cluster.ActorSystemProvider;
 import org.opendaylight.controller.config.threadpool.ScheduledThreadPool;
@@ -96,6 +97,9 @@ import org.opendaylight.mdsal.singleton.common.api.ServiceGroupIdentifier;
 import org.opendaylight.mdsal.singleton.dom.impl.DOMClusterSingletonServiceProviderImpl;
 import org.opendaylight.netconf.client.NetconfClientDispatcher;
 import org.opendaylight.netconf.sal.connect.api.DeviceActionFactory;
 import org.opendaylight.mdsal.singleton.dom.impl.DOMClusterSingletonServiceProviderImpl;
 import org.opendaylight.netconf.client.NetconfClientDispatcher;
 import org.opendaylight.netconf.sal.connect.api.DeviceActionFactory;
+import org.opendaylight.netconf.sal.connect.api.SchemaResourceManager;
+import org.opendaylight.netconf.sal.connect.impl.DefaultSchemaResourceManager;
+import org.opendaylight.netconf.sal.connect.netconf.NetconfDevice.SchemaResourcesDTO;
 import org.opendaylight.netconf.sal.connect.netconf.listener.NetconfSessionPreferences;
 import org.opendaylight.netconf.topology.singleton.impl.utils.ClusteringRpcException;
 import org.opendaylight.netconf.topology.singleton.impl.utils.NetconfTopologySetup;
 import org.opendaylight.netconf.sal.connect.netconf.listener.NetconfSessionPreferences;
 import org.opendaylight.netconf.topology.singleton.impl.utils.ClusteringRpcException;
 import org.opendaylight.netconf.topology.singleton.impl.utils.NetconfTopologySetup;
@@ -156,6 +160,7 @@ import org.slf4j.LoggerFactory;
  *
  * @author Thomas Pantelis
  */
  *
  * @author Thomas Pantelis
  */
+@RunWith(MockitoJUnitRunner.class)
 public class MountPointEndToEndTest {
     private static final Logger LOG = LoggerFactory.getLogger(MountPointEndToEndTest.class);
 
 public class MountPointEndToEndTest {
     private static final Logger LOG = LoggerFactory.getLogger(MountPointEndToEndTest.class);
 
@@ -166,6 +171,9 @@ public class MountPointEndToEndTest {
     private static final InstanceIdentifier<Node> NODE_INSTANCE_ID = NetconfTopologyUtils.createTopologyNodeListPath(
             new NodeKey(NODE_ID), TOPOLOGY_ID);
 
     private static final InstanceIdentifier<Node> NODE_INSTANCE_ID = NetconfTopologyUtils.createTopologyNodeListPath(
             new NodeKey(NODE_ID), TOPOLOGY_ID);
 
+    private static final String TEST_ROOT_DIRECTORY = "test-cache-root";
+    private static final String TEST_DEFAULT_SUBDIR = "test-schema";
+
     @Mock private DOMRpcProviderService mockRpcProviderRegistry;
     @Mock private DOMActionProviderService mockActionProviderRegistry;
     @Mock private NetconfClientDispatcher mockClientDispatcher;
     @Mock private DOMRpcProviderService mockRpcProviderRegistry;
     @Mock private DOMActionProviderService mockActionProviderRegistry;
     @Mock private NetconfClientDispatcher mockClientDispatcher;
@@ -206,13 +214,15 @@ public class MountPointEndToEndTest {
     private YangInstanceIdentifier yangNodeInstanceId;
     private final TopDOMRpcImplementation topRpcImplementation = new TopDOMRpcImplementation();
 
     private YangInstanceIdentifier yangNodeInstanceId;
     private final TopDOMRpcImplementation topRpcImplementation = new TopDOMRpcImplementation();
 
+    private SchemaResourceManager resourceManager;
+
     @SuppressWarnings({ "unchecked", "rawtypes" })
     @Before
     public void setUp() throws Exception {
     @SuppressWarnings({ "unchecked", "rawtypes" })
     @Before
     public void setUp() throws Exception {
-        initMocks(this);
-
         deleteCacheDir();
 
         deleteCacheDir();
 
+        resourceManager = new DefaultSchemaResourceManager(TEST_ROOT_DIRECTORY, TEST_DEFAULT_SUBDIR);
+
         topModuleInfo = BindingReflections.getModuleInfo(Top.class);
 
         final ModuleInfoBackedContext moduleContext = ModuleInfoBackedContext.create();
         topModuleInfo = BindingReflections.getModuleInfo(Top.class);
 
         final ModuleInfoBackedContext moduleContext = ModuleInfoBackedContext.create();
@@ -240,7 +250,7 @@ public class MountPointEndToEndTest {
     }
 
     private static void deleteCacheDir() {
     }
 
     private static void deleteCacheDir() {
-        FileUtils.deleteQuietly(new File(NetconfTopologyUtils.CACHE_DIRECTORY));
+        FileUtils.deleteQuietly(new File(TEST_ROOT_DIRECTORY));
     }
 
     @After
     }
 
     @After
@@ -266,7 +276,9 @@ public class MountPointEndToEndTest {
 
         doReturn(MoreExecutors.newDirectExecutorService()).when(mockThreadPool).getExecutor();
 
 
         doReturn(MoreExecutors.newDirectExecutorService()).when(mockThreadPool).getExecutor();
 
-        NetconfTopologyUtils.DEFAULT_SCHEMA_REPOSITORY.registerSchemaSource(
+        final SchemaResourcesDTO resources =  resourceManager.getSchemaResources(
+            new NetconfNodeBuilder().setSchemaCacheDirectory(TEST_DEFAULT_SUBDIR).build(), "test");
+        resources.getSchemaRegistry().registerSchemaSource(
             id -> Futures.immediateFuture(YangTextSchemaSource.delegateForByteSource(id,
                     topModuleInfo.getYangTextByteSource())),
             PotentialSchemaSource.create(RevisionSourceIdentifier.create(TOP_MODULE_NAME,
             id -> Futures.immediateFuture(YangTextSchemaSource.delegateForByteSource(id,
                     topModuleInfo.getYangTextByteSource())),
             PotentialSchemaSource.create(RevisionSourceIdentifier.create(TOP_MODULE_NAME,
@@ -275,7 +287,7 @@ public class MountPointEndToEndTest {
         masterNetconfTopologyManager = new NetconfTopologyManager(masterDataBroker, mockRpcProviderRegistry,
             mockActionProviderRegistry, masterClusterSingletonServiceProvider, mockKeepaliveExecutor, mockThreadPool,
                 mockMasterActorSystemProvider, eventExecutor, mockClientDispatcher, TOPOLOGY_ID, config,
         masterNetconfTopologyManager = new NetconfTopologyManager(masterDataBroker, mockRpcProviderRegistry,
             mockActionProviderRegistry, masterClusterSingletonServiceProvider, mockKeepaliveExecutor, mockThreadPool,
                 mockMasterActorSystemProvider, eventExecutor, mockClientDispatcher, TOPOLOGY_ID, config,
-                masterMountPointService, mockEncryptionService, deviceActionFactory) {
+                masterMountPointService, mockEncryptionService, deviceActionFactory, resourceManager) {
             @Override
             protected NetconfTopologyContext newNetconfTopologyContext(final NetconfTopologySetup setup,
                 final ServiceGroupIdentifier serviceGroupIdent, final Timeout actorResponseWaitTime,
             @Override
             protected NetconfTopologyContext newNetconfTopologyContext(final NetconfTopologySetup setup,
                 final ServiceGroupIdentifier serviceGroupIdent, final Timeout actorResponseWaitTime,
@@ -314,7 +326,7 @@ public class MountPointEndToEndTest {
         slaveNetconfTopologyManager = new NetconfTopologyManager(slaveDataBroker, mockRpcProviderRegistry,
             mockActionProviderRegistry, mockSlaveClusterSingletonServiceProvider, mockKeepaliveExecutor, mockThreadPool,
                 mockSlaveActorSystemProvider, eventExecutor, mockClientDispatcher, TOPOLOGY_ID, config,
         slaveNetconfTopologyManager = new NetconfTopologyManager(slaveDataBroker, mockRpcProviderRegistry,
             mockActionProviderRegistry, mockSlaveClusterSingletonServiceProvider, mockKeepaliveExecutor, mockThreadPool,
                 mockSlaveActorSystemProvider, eventExecutor, mockClientDispatcher, TOPOLOGY_ID, config,
-                slaveMountPointService, mockEncryptionService, deviceActionFactory) {
+                slaveMountPointService, mockEncryptionService, deviceActionFactory, resourceManager) {
             @Override
             protected NetconfTopologyContext newNetconfTopologyContext(final NetconfTopologySetup setup,
                 final ServiceGroupIdentifier serviceGroupIdent, final Timeout actorResponseWaitTime,
             @Override
             protected NetconfTopologyContext newNetconfTopologyContext(final NetconfTopologySetup setup,
                 final ServiceGroupIdentifier serviceGroupIdent, final Timeout actorResponseWaitTime,
@@ -360,7 +372,7 @@ public class MountPointEndToEndTest {
     private MasterSalFacade testMaster() throws InterruptedException, ExecutionException, TimeoutException {
         LOG.info("****** Testing master");
 
     private MasterSalFacade testMaster() throws InterruptedException, ExecutionException, TimeoutException {
         LOG.info("****** Testing master");
 
-        writeNetconfNode(NetconfTopologyUtils.DEFAULT_CACHE_DIRECTORY, masterDataBroker);
+        writeNetconfNode(TEST_DEFAULT_SUBDIR, masterDataBroker);
 
         final MasterSalFacade masterSalFacade = masterSalFacadeFuture.get(5, TimeUnit.SECONDS);
 
 
         final MasterSalFacade masterSalFacade = masterSalFacadeFuture.get(5, TimeUnit.SECONDS);
 
@@ -433,7 +445,7 @@ public class MountPointEndToEndTest {
         slaveMountPointService.registerProvisionListener(slaveMountPointListener);
 
         masterSalFacadeFuture = SettableFuture.create();
         slaveMountPointService.registerProvisionListener(slaveMountPointListener);
 
         masterSalFacadeFuture = SettableFuture.create();
-        writeNetconfNode(NetconfTopologyUtils.DEFAULT_CACHE_DIRECTORY, masterDataBroker);
+        writeNetconfNode(TEST_DEFAULT_SUBDIR, masterDataBroker);
 
         verify(masterMountPointListener, timeout(5000)).onMountPointRemoved(yangNodeInstanceId);
 
 
         verify(masterMountPointListener, timeout(5000)).onMountPointRemoved(yangNodeInstanceId);
 
index 6e6d3d6f5ec11288fa33e97c2200089eceb5cdee..8fc8473b4542302188abcfc04db477ca5c0bd328 100644 (file)
@@ -26,7 +26,6 @@ import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.verifyNoMoreInteractions;
 import static org.mockito.MockitoAnnotations.initMocks;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.verifyNoMoreInteractions;
 import static org.mockito.MockitoAnnotations.initMocks;
-import static org.opendaylight.netconf.topology.singleton.impl.utils.NetconfTopologyUtils.DEFAULT_SCHEMA_REPOSITORY;
 
 import akka.actor.ActorRef;
 import akka.actor.ActorSystem;
 
 import akka.actor.ActorRef;
 import akka.actor.ActorSystem;
@@ -408,9 +407,11 @@ public class NetconfNodeActorTest {
 
     @Test(expected = MissingSchemaSourceException.class)
     public void testMissingSchemaSourceOnMissingProvider() throws Exception {
 
     @Test(expected = MissingSchemaSourceException.class)
     public void testMissingSchemaSourceOnMissingProvider() throws Exception {
+        final SharedSchemaRepository repository = new SharedSchemaRepository("test");
+
         SchemaResourcesDTO schemaResourceDTO2 = mock(SchemaResourcesDTO.class);
         SchemaResourcesDTO schemaResourceDTO2 = mock(SchemaResourcesDTO.class);
-        doReturn(DEFAULT_SCHEMA_REPOSITORY).when(schemaResourceDTO2).getSchemaRegistry();
-        doReturn(DEFAULT_SCHEMA_REPOSITORY).when(schemaResourceDTO2).getSchemaRepository();
+        doReturn(repository).when(schemaResourceDTO2).getSchemaRegistry();
+        doReturn(repository).when(schemaResourceDTO2).getSchemaRepository();
         final NetconfTopologySetup setup = NetconfTopologySetupBuilder.create().setActorSystem(system)
                 .setSchemaResourceDTO(schemaResourceDTO2).setIdleTimeout(Duration.apply(1, TimeUnit.SECONDS)).build();
         final Props props = NetconfNodeActor.props(setup, remoteDeviceId, TIMEOUT, mockMountPointService);
         final NetconfTopologySetup setup = NetconfTopologySetupBuilder.create().setActorSystem(system)
                 .setSchemaResourceDTO(schemaResourceDTO2).setIdleTimeout(Duration.apply(1, TimeUnit.SECONDS)).build();
         final Props props = NetconfNodeActor.props(setup, remoteDeviceId, TIMEOUT, mockMountPointService);
index 82b2d325cb11437ca2b47d8edb4f7bafb2472920..fe0e001268d3e0ab9112c48ab080ad1b6a066472 100644 (file)
@@ -60,6 +60,7 @@ import org.opendaylight.mdsal.singleton.common.api.ClusterSingletonServiceRegist
 import org.opendaylight.mdsal.singleton.common.api.ServiceGroupIdentifier;
 import org.opendaylight.netconf.client.NetconfClientDispatcher;
 import org.opendaylight.netconf.sal.connect.api.DeviceActionFactory;
 import org.opendaylight.mdsal.singleton.common.api.ServiceGroupIdentifier;
 import org.opendaylight.netconf.client.NetconfClientDispatcher;
 import org.opendaylight.netconf.sal.connect.api.DeviceActionFactory;
+import org.opendaylight.netconf.sal.connect.impl.DefaultSchemaResourceManager;
 import org.opendaylight.netconf.topology.singleton.impl.utils.NetconfTopologySetup;
 import org.opendaylight.netconf.topology.singleton.impl.utils.NetconfTopologyUtils;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Host;
 import org.opendaylight.netconf.topology.singleton.impl.utils.NetconfTopologySetup;
 import org.opendaylight.netconf.topology.singleton.impl.utils.NetconfTopologyUtils;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Host;
@@ -130,7 +131,7 @@ public class NetconfTopologyManagerTest {
         netconfTopologyManager = new NetconfTopologyManager(dataBroker, rpcProviderRegistry, actionProviderRegistry,
                 clusterSingletonServiceProvider, keepaliveExecutor, processingThreadPool,
                 actorSystemProvider, eventExecutor, clientDispatcher, TOPOLOGY_ID, config,
         netconfTopologyManager = new NetconfTopologyManager(dataBroker, rpcProviderRegistry, actionProviderRegistry,
                 clusterSingletonServiceProvider, keepaliveExecutor, processingThreadPool,
                 actorSystemProvider, eventExecutor, clientDispatcher, TOPOLOGY_ID, config,
-                mountPointService, encryptionService, deviceActionFactory) {
+                mountPointService, encryptionService, deviceActionFactory, new DefaultSchemaResourceManager()) {
             @Override
             protected NetconfTopologyContext newNetconfTopologyContext(final NetconfTopologySetup setup,
                 final ServiceGroupIdentifier serviceGroupIdent, final Timeout actorResponseWaitTime,
             @Override
             protected NetconfTopologyContext newNetconfTopologyContext(final NetconfTopologySetup setup,
                 final ServiceGroupIdentifier serviceGroupIdent, final Timeout actorResponseWaitTime,
index 8fa8ee6357b426a603bdb81fcc8e69a856dce29f..48dfab7f5f825f5bc0e1910b3614ed679b50ce01 100644 (file)
@@ -44,13 +44,13 @@ import org.opendaylight.netconf.client.conf.NetconfClientConfiguration;
 import org.opendaylight.netconf.client.conf.NetconfReconnectingClientConfiguration;
 import org.opendaylight.netconf.sal.connect.api.DeviceActionFactory;
 import org.opendaylight.netconf.sal.connect.api.RemoteDeviceHandler;
 import org.opendaylight.netconf.client.conf.NetconfReconnectingClientConfiguration;
 import org.opendaylight.netconf.sal.connect.api.DeviceActionFactory;
 import org.opendaylight.netconf.sal.connect.api.RemoteDeviceHandler;
+import org.opendaylight.netconf.sal.connect.impl.DefaultSchemaResourceManager;
 import org.opendaylight.netconf.sal.connect.netconf.listener.NetconfDeviceCommunicator;
 import org.opendaylight.netconf.sal.connect.netconf.listener.NetconfSessionPreferences;
 import org.opendaylight.netconf.sal.connect.netconf.sal.KeepaliveSalFacade;
 import org.opendaylight.netconf.sal.connect.util.RemoteDeviceId;
 import org.opendaylight.netconf.topology.singleton.impl.utils.NetconfConnectorDTO;
 import org.opendaylight.netconf.topology.singleton.impl.utils.NetconfTopologySetup;
 import org.opendaylight.netconf.sal.connect.netconf.listener.NetconfDeviceCommunicator;
 import org.opendaylight.netconf.sal.connect.netconf.listener.NetconfSessionPreferences;
 import org.opendaylight.netconf.sal.connect.netconf.sal.KeepaliveSalFacade;
 import org.opendaylight.netconf.sal.connect.util.RemoteDeviceId;
 import org.opendaylight.netconf.topology.singleton.impl.utils.NetconfConnectorDTO;
 import org.opendaylight.netconf.topology.singleton.impl.utils.NetconfTopologySetup;
-import org.opendaylight.netconf.topology.singleton.impl.utils.NetconfTopologyUtils;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Host;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Address;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Host;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Address;
@@ -188,7 +188,8 @@ public class RemoteDeviceConnectorImplTest {
                 .build();
 
         final Node node = new NodeBuilder().setNodeId(NODE_ID).addAugmentation(NetconfNode.class, netconfNode).build();
                 .build();
 
         final Node node = new NodeBuilder().setNodeId(NODE_ID).addAugmentation(NetconfNode.class, netconfNode).build();
-        builder.setSchemaResourceDTO(NetconfTopologyUtils.setupSchemaCacheDTO(node));
+
+        builder.setSchemaResourceDTO(new DefaultSchemaResourceManager().getSchemaResources(netconfNode, "foo"));
 
         final RemoteDeviceConnectorImpl remoteDeviceConnection =
                 new RemoteDeviceConnectorImpl(builder.build(), remoteDeviceId, deviceActionFactory);
 
         final RemoteDeviceConnectorImpl remoteDeviceConnection =
                 new RemoteDeviceConnectorImpl(builder.build(), remoteDeviceId, deviceActionFactory);
diff --git a/netconf/netconf-topology/src/main/java/org/opendaylight/netconf/topology/api/SchemaRepositoryProvider.java b/netconf/netconf-topology/src/main/java/org/opendaylight/netconf/topology/api/SchemaRepositoryProvider.java
deleted file mode 100644 (file)
index c0c38cf..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-/*
- * Copyright (c) 2015 Cisco Systems, Inc. and others. All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-package org.opendaylight.netconf.topology.api;
-
-import org.eclipse.jdt.annotation.NonNull;
-import org.opendaylight.yangtools.yang.parser.repo.SharedSchemaRepository;
-
-public interface SchemaRepositoryProvider {
-
-    @NonNull SharedSchemaRepository getSharedSchemaRepository();
-}
index fd31e9a7589a459f1043734af752c7f7da5ccd5f..478ca7f6e328d7e66e3e39d1ce7dd42baf2f53f8 100644 (file)
@@ -11,16 +11,13 @@ import static java.util.Objects.requireNonNull;
 
 import com.google.common.annotations.VisibleForTesting;
 import com.google.common.base.Preconditions;
 
 import com.google.common.annotations.VisibleForTesting;
 import com.google.common.base.Preconditions;
-import com.google.common.base.Strings;
 import com.google.common.collect.Lists;
 import com.google.common.util.concurrent.FutureCallback;
 import com.google.common.util.concurrent.Futures;
 import com.google.common.util.concurrent.ListenableFuture;
 import com.google.common.util.concurrent.ListeningExecutorService;
 import com.google.common.util.concurrent.MoreExecutors;
 import com.google.common.collect.Lists;
 import com.google.common.util.concurrent.FutureCallback;
 import com.google.common.util.concurrent.Futures;
 import com.google.common.util.concurrent.ListenableFuture;
 import com.google.common.util.concurrent.ListeningExecutorService;
 import com.google.common.util.concurrent.MoreExecutors;
-import com.google.common.util.concurrent.Uninterruptibles;
 import io.netty.util.concurrent.EventExecutor;
 import io.netty.util.concurrent.EventExecutor;
-import java.io.File;
 import java.math.BigDecimal;
 import java.net.InetSocketAddress;
 import java.net.URL;
 import java.math.BigDecimal;
 import java.net.InetSocketAddress;
 import java.net.URL;
@@ -29,7 +26,6 @@ import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.Optional;
 import java.util.List;
 import java.util.Map;
 import java.util.Optional;
-import java.util.concurrent.TimeUnit;
 import org.opendaylight.aaa.encrypt.AAAEncryptionService;
 import org.opendaylight.controller.config.threadpool.ScheduledThreadPool;
 import org.opendaylight.controller.config.threadpool.ThreadPool;
 import org.opendaylight.aaa.encrypt.AAAEncryptionService;
 import org.opendaylight.controller.config.threadpool.ScheduledThreadPool;
 import org.opendaylight.controller.config.threadpool.ThreadPool;
@@ -48,10 +44,11 @@ import org.opendaylight.netconf.nettyutil.handler.ssh.authentication.LoginPasswo
 import org.opendaylight.netconf.sal.connect.api.DeviceActionFactory;
 import org.opendaylight.netconf.sal.connect.api.RemoteDevice;
 import org.opendaylight.netconf.sal.connect.api.RemoteDeviceHandler;
 import org.opendaylight.netconf.sal.connect.api.DeviceActionFactory;
 import org.opendaylight.netconf.sal.connect.api.RemoteDevice;
 import org.opendaylight.netconf.sal.connect.api.RemoteDeviceHandler;
+import org.opendaylight.netconf.sal.connect.api.SchemaResourceManager;
 import org.opendaylight.netconf.sal.connect.netconf.LibraryModulesSchemas;
 import org.opendaylight.netconf.sal.connect.netconf.NetconfDevice;
 import org.opendaylight.netconf.sal.connect.netconf.LibraryModulesSchemas;
 import org.opendaylight.netconf.sal.connect.netconf.NetconfDevice;
+import org.opendaylight.netconf.sal.connect.netconf.NetconfDevice.SchemaResourcesDTO;
 import org.opendaylight.netconf.sal.connect.netconf.NetconfDeviceBuilder;
 import org.opendaylight.netconf.sal.connect.netconf.NetconfDeviceBuilder;
-import org.opendaylight.netconf.sal.connect.netconf.NetconfStateSchemasResolverImpl;
 import org.opendaylight.netconf.sal.connect.netconf.SchemalessNetconfDevice;
 import org.opendaylight.netconf.sal.connect.netconf.auth.DatastoreBackedPublicKeyAuth;
 import org.opendaylight.netconf.sal.connect.netconf.listener.NetconfDeviceCapabilities;
 import org.opendaylight.netconf.sal.connect.netconf.SchemalessNetconfDevice;
 import org.opendaylight.netconf.sal.connect.netconf.auth.DatastoreBackedPublicKeyAuth;
 import org.opendaylight.netconf.sal.connect.netconf.listener.NetconfDeviceCapabilities;
@@ -64,9 +61,9 @@ import org.opendaylight.netconf.sal.connect.netconf.schema.YangLibrarySchemaYang
 import org.opendaylight.netconf.sal.connect.util.RemoteDeviceId;
 import org.opendaylight.netconf.sal.connect.util.SslHandlerFactoryImpl;
 import org.opendaylight.netconf.topology.api.NetconfTopology;
 import org.opendaylight.netconf.sal.connect.util.RemoteDeviceId;
 import org.opendaylight.netconf.sal.connect.util.SslHandlerFactoryImpl;
 import org.opendaylight.netconf.topology.api.NetconfTopology;
-import org.opendaylight.netconf.topology.api.SchemaRepositoryProvider;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Host;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Host;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Uri;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.optional.rev190614.NetconfNodeAugmentedOptional;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.NetconfNode;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.netconf.node.connection.parameters.Protocol;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.optional.rev190614.NetconfNodeAugmentedOptional;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.NetconfNode;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.netconf.node.connection.parameters.Protocol;
@@ -79,27 +76,18 @@ import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev15
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.netconf.node.credentials.credentials.key.auth.KeyBased;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.netconf.node.credentials.credentials.login.pw.LoginPassword;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.netconf.node.credentials.credentials.login.pw.unencrypted.LoginPasswordUnencrypted;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.netconf.node.credentials.credentials.key.auth.KeyBased;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.netconf.node.credentials.credentials.login.pw.LoginPassword;
 import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.netconf.node.credentials.credentials.login.pw.unencrypted.LoginPasswordUnencrypted;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.netconf.schema.storage.YangLibrary;
 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NodeId;
 import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
-import org.opendaylight.yangtools.yang.model.repo.api.EffectiveModelContextFactory;
-import org.opendaylight.yangtools.yang.model.repo.api.SchemaContextFactory;
-import org.opendaylight.yangtools.yang.model.repo.api.SchemaContextFactoryConfiguration;
-import org.opendaylight.yangtools.yang.model.repo.api.SchemaRepository;
 import org.opendaylight.yangtools.yang.model.repo.api.SourceIdentifier;
 import org.opendaylight.yangtools.yang.model.repo.api.YangTextSchemaSource;
 import org.opendaylight.yangtools.yang.model.repo.spi.PotentialSchemaSource;
 import org.opendaylight.yangtools.yang.model.repo.spi.SchemaSourceRegistration;
 import org.opendaylight.yangtools.yang.model.repo.spi.SchemaSourceRegistry;
 import org.opendaylight.yangtools.yang.model.repo.api.SourceIdentifier;
 import org.opendaylight.yangtools.yang.model.repo.api.YangTextSchemaSource;
 import org.opendaylight.yangtools.yang.model.repo.spi.PotentialSchemaSource;
 import org.opendaylight.yangtools.yang.model.repo.spi.SchemaSourceRegistration;
 import org.opendaylight.yangtools.yang.model.repo.spi.SchemaSourceRegistry;
-import org.opendaylight.yangtools.yang.model.repo.util.FilesystemSchemaSourceCache;
-import org.opendaylight.yangtools.yang.model.repo.util.InMemorySchemaSourceCache;
-import org.opendaylight.yangtools.yang.parser.repo.SharedSchemaRepository;
-import org.opendaylight.yangtools.yang.parser.rfc7950.repo.ASTSchemaSource;
-import org.opendaylight.yangtools.yang.parser.rfc7950.repo.TextToASTTransformer;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 public abstract class AbstractNetconfTopology implements NetconfTopology {
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 public abstract class AbstractNetconfTopology implements NetconfTopology {
-
     private static final Logger LOG = LoggerFactory.getLogger(AbstractNetconfTopology.class);
 
     protected static final long DEFAULT_REQUEST_TIMEOUT_MILLIS = 60000L;
     private static final Logger LOG = LoggerFactory.getLogger(AbstractNetconfTopology.class);
 
     protected static final long DEFAULT_REQUEST_TIMEOUT_MILLIS = 60000L;
@@ -112,103 +100,18 @@ public abstract class AbstractNetconfTopology implements NetconfTopology {
     private static final long DEFAULT_CONNECTION_TIMEOUT_MILLIS = 20000L;
     private static final BigDecimal DEFAULT_SLEEP_FACTOR = new BigDecimal(1.5);
 
     private static final long DEFAULT_CONNECTION_TIMEOUT_MILLIS = 20000L;
     private static final BigDecimal DEFAULT_SLEEP_FACTOR = new BigDecimal(1.5);
 
-    // constants related to Schema Cache(s)
-    /**
-     * Filesystem based caches are stored relative to the cache directory.
-     */
-    private static final String CACHE_DIRECTORY = "cache";
-
-    /**
-     * The default cache directory relative to <code>CACHE_DIRECTORY</code>.
-     */
-    private static final String DEFAULT_CACHE_DIRECTORY = "schema";
-
-    /**
-     * The qualified schema cache directory <code>cache/schema</code>.
-     */
-    private static final String QUALIFIED_DEFAULT_CACHE_DIRECTORY =
-            CACHE_DIRECTORY + File.separator + DEFAULT_CACHE_DIRECTORY;
-
-    /**
-     * The name for the default schema repository.
-     */
-    private static final String DEFAULT_SCHEMA_REPOSITORY_NAME = "sal-netconf-connector";
-
-    /**
-     * The default schema repository in the case that one is not specified.
-     */
-    private static final SharedSchemaRepository DEFAULT_SCHEMA_REPOSITORY =
-            new SharedSchemaRepository(DEFAULT_SCHEMA_REPOSITORY_NAME);
-
-    public static final InMemorySchemaSourceCache<ASTSchemaSource> DEFAULT_AST_CACHE =
-            InMemorySchemaSourceCache.createSoftCache(DEFAULT_SCHEMA_REPOSITORY, ASTSchemaSource.class);
-
-    /**
-     * The default factory for creating <code>SchemaContext</code> instances.
-     */
-    private static final EffectiveModelContextFactory DEFAULT_SCHEMA_CONTEXT_FACTORY =
-            DEFAULT_SCHEMA_REPOSITORY.createEffectiveModelContextFactory(
-                SchemaContextFactoryConfiguration.getDefault());
-
-    /**
-     * Keeps track of initialized Schema resources.  A Map is maintained in which the key represents the name
-     * of the schema cache directory, and the value is a corresponding <code>SchemaResourcesDTO</code>.  The
-     * <code>SchemaResourcesDTO</code> is essentially a container that allows for the extraction of the
-     * <code>SchemaRegistry</code> and <code>SchemaContextFactory</code> which should be used for a particular
-     * Netconf mount.  Access to <code>SCHEMA_RESOURCES_DTO_MAP</code> should be surrounded by appropriate
-     * synchronization locks.
-     */
-    private static final Map<String, NetconfDevice.SchemaResourcesDTO> SCHEMA_RESOURCES_DTO_MAP = new HashMap<>();
-
-    // Initializes default constant instances for the case when the default schema repository
-    // directory cache/schema is used.
-    static {
-        SCHEMA_RESOURCES_DTO_MAP.put(DEFAULT_CACHE_DIRECTORY,
-                new NetconfDevice.SchemaResourcesDTO(DEFAULT_SCHEMA_REPOSITORY, DEFAULT_SCHEMA_REPOSITORY,
-                        DEFAULT_SCHEMA_CONTEXT_FACTORY,
-                        new NetconfStateSchemasResolverImpl()));
-        DEFAULT_SCHEMA_REPOSITORY.registerSchemaSourceListener(DEFAULT_AST_CACHE);
-        DEFAULT_SCHEMA_REPOSITORY.registerSchemaSourceListener(
-                TextToASTTransformer.create(DEFAULT_SCHEMA_REPOSITORY, DEFAULT_SCHEMA_REPOSITORY));
-
-        /*
-         * Create the default <code>FilesystemSchemaSourceCache</code>, which stores cached files
-         * in <code>cache/schema</code>. Try up to 3 times - we've seen intermittent failures on jenkins where
-         * FilesystemSchemaSourceCache throws an IAE due to mkdirs failure. The theory is that there's a race
-         * creating the dir and it already exists when mkdirs is called (mkdirs returns false in this case). In this
-         * scenario, a retry should succeed.
-         */
-        int tries = 1;
-        while (true) {
-            try {
-                FilesystemSchemaSourceCache<YangTextSchemaSource> defaultCache =
-                        new FilesystemSchemaSourceCache<>(DEFAULT_SCHEMA_REPOSITORY, YangTextSchemaSource.class,
-                                new File(QUALIFIED_DEFAULT_CACHE_DIRECTORY));
-                DEFAULT_SCHEMA_REPOSITORY.registerSchemaSourceListener(defaultCache);
-                break;
-            } catch (IllegalArgumentException e) {
-                if (tries++ >= 3) {
-                    LOG.error("Error creating default schema cache", e);
-                    break;
-                }
-                Uninterruptibles.sleepUninterruptibly(100, TimeUnit.MILLISECONDS);
-            }
-        }
-    }
 
     private final NetconfClientDispatcher clientDispatcher;
     private final EventExecutor eventExecutor;
     private final DeviceActionFactory deviceActionFactory;
     private final NetconfKeystoreAdapter keystoreAdapter;
 
     private final NetconfClientDispatcher clientDispatcher;
     private final EventExecutor eventExecutor;
     private final DeviceActionFactory deviceActionFactory;
     private final NetconfKeystoreAdapter keystoreAdapter;
+    private final SchemaResourceManager schemaManager;
+
     protected final ScheduledThreadPool keepaliveExecutor;
     protected final ListeningExecutorService processingExecutor;
     protected final ScheduledThreadPool keepaliveExecutor;
     protected final ListeningExecutorService processingExecutor;
-    protected final SharedSchemaRepository sharedSchemaRepository;
     protected final DataBroker dataBroker;
     protected final DOMMountPointService mountPointService;
     protected final String topologyId;
     protected final DataBroker dataBroker;
     protected final DOMMountPointService mountPointService;
     protected final String topologyId;
-    protected SchemaSourceRegistry schemaRegistry = DEFAULT_SCHEMA_REPOSITORY;
-    protected SchemaRepository schemaRepository = DEFAULT_SCHEMA_REPOSITORY;
-    protected SchemaContextFactory schemaContextFactory = DEFAULT_SCHEMA_CONTEXT_FACTORY;
     protected String privateKeyPath;
     protected String privateKeyPassphrase;
     protected final AAAEncryptionService encryptionService;
     protected String privateKeyPath;
     protected String privateKeyPassphrase;
     protected final AAAEncryptionService encryptionService;
@@ -216,8 +119,7 @@ public abstract class AbstractNetconfTopology implements NetconfTopology {
 
     protected AbstractNetconfTopology(final String topologyId, final NetconfClientDispatcher clientDispatcher,
                                       final EventExecutor eventExecutor, final ScheduledThreadPool keepaliveExecutor,
 
     protected AbstractNetconfTopology(final String topologyId, final NetconfClientDispatcher clientDispatcher,
                                       final EventExecutor eventExecutor, final ScheduledThreadPool keepaliveExecutor,
-                                      final ThreadPool processingExecutor,
-                                      final SchemaRepositoryProvider schemaRepositoryProvider,
+                                      final ThreadPool processingExecutor, final SchemaResourceManager schemaManager,
                                       final DataBroker dataBroker, final DOMMountPointService mountPointService,
                                       final AAAEncryptionService encryptionService,
                                       final DeviceActionFactory deviceActionFactory) {
                                       final DataBroker dataBroker, final DOMMountPointService mountPointService,
                                       final AAAEncryptionService encryptionService,
                                       final DeviceActionFactory deviceActionFactory) {
@@ -226,8 +128,8 @@ public abstract class AbstractNetconfTopology implements NetconfTopology {
         this.eventExecutor = eventExecutor;
         this.keepaliveExecutor = keepaliveExecutor;
         this.processingExecutor = MoreExecutors.listeningDecorator(processingExecutor.getExecutor());
         this.eventExecutor = eventExecutor;
         this.keepaliveExecutor = keepaliveExecutor;
         this.processingExecutor = MoreExecutors.listeningDecorator(processingExecutor.getExecutor());
+        this.schemaManager = requireNonNull(schemaManager);
         this.deviceActionFactory = deviceActionFactory;
         this.deviceActionFactory = deviceActionFactory;
-        this.sharedSchemaRepository = schemaRepositoryProvider.getSharedSchemaRepository();
         this.dataBroker = dataBroker;
         this.mountPointService = mountPointService;
         this.encryptionService = encryptionService;
         this.dataBroker = dataBroker;
         this.mountPointService = mountPointService;
         this.encryptionService = encryptionService;
@@ -235,14 +137,6 @@ public abstract class AbstractNetconfTopology implements NetconfTopology {
         this.keystoreAdapter = new NetconfKeystoreAdapter(dataBroker);
     }
 
         this.keystoreAdapter = new NetconfKeystoreAdapter(dataBroker);
     }
 
-    public void setSchemaRegistry(final SchemaSourceRegistry schemaRegistry) {
-        this.schemaRegistry = schemaRegistry;
-    }
-
-    public void setSchemaContextFactory(final SchemaContextFactory schemaContextFactory) {
-        this.schemaContextFactory = schemaContextFactory;
-    }
-
     @Override
     public ListenableFuture<NetconfDeviceCapabilities> connectNode(final NodeId nodeId, final Node configNode) {
         LOG.info("Connecting RemoteDevice{{}} , with config {}", nodeId, hideCredentials(configNode));
     @Override
     public ListenableFuture<NetconfDeviceCapabilities> connectNode(final NodeId nodeId, final Node configNode) {
         LOG.info("Connecting RemoteDevice{{}} , with config {}", nodeId, hideCredentials(configNode));
@@ -323,8 +217,6 @@ public abstract class AbstractNetconfTopology implements NetconfTopology {
                 ? DEFAULT_REQUEST_TIMEOUT_MILLIS : node.getDefaultRequestTimeoutMillis().toJava();
         final long keepaliveDelay = node.getKeepaliveDelay() == null
                 ? DEFAULT_KEEPALIVE_DELAY : node.getKeepaliveDelay().toJava();
                 ? DEFAULT_REQUEST_TIMEOUT_MILLIS : node.getDefaultRequestTimeoutMillis().toJava();
         final long keepaliveDelay = node.getKeepaliveDelay() == null
                 ? DEFAULT_KEEPALIVE_DELAY : node.getKeepaliveDelay().toJava();
-        final boolean reconnectOnChangedSchema = node.isReconnectOnChangedSchema() == null
-                ? DEFAULT_RECONNECT_ON_CHANGED_SCHEMA : node.isReconnectOnChangedSchema();
 
         final IpAddress ipAddress = node.getHost().getIpAddress();
         final InetSocketAddress address = new InetSocketAddress(ipAddress.getIpv4Address() != null
 
         final IpAddress ipAddress = node.getHost().getIpAddress();
         final InetSocketAddress address = new InetSocketAddress(ipAddress.getIpv4Address() != null
@@ -332,8 +224,7 @@ public abstract class AbstractNetconfTopology implements NetconfTopology {
                 node.getPort().getValue().toJava());
         final RemoteDeviceId remoteDeviceId = new RemoteDeviceId(nodeId.getValue(), address);
 
                 node.getPort().getValue().toJava());
         final RemoteDeviceId remoteDeviceId = new RemoteDeviceId(nodeId.getValue(), address);
 
-        RemoteDeviceHandler<NetconfSessionPreferences> salFacade =
-                createSalFacade(remoteDeviceId);
+        RemoteDeviceHandler<NetconfSessionPreferences> salFacade = createSalFacade(remoteDeviceId);
 
         if (keepaliveDelay > 0) {
             LOG.warn("Adding keepalive facade, for device {}", nodeId);
 
         if (keepaliveDelay > 0) {
             LOG.warn("Adding keepalive facade, for device {}", nodeId);
@@ -341,49 +232,11 @@ public abstract class AbstractNetconfTopology implements NetconfTopology {
                     keepaliveDelay, defaultRequestTimeoutMillis);
         }
 
                     keepaliveDelay, defaultRequestTimeoutMillis);
         }
 
-        // pre register yang library sources as fallback schemas to schema registry
-        final List<SchemaSourceRegistration<YangTextSchemaSource>> registeredYangLibSources = Lists.newArrayList();
-        if (node.getYangLibrary() != null) {
-            final String yangLibURL = node.getYangLibrary().getYangLibraryUrl().getValue();
-            final String yangLibUsername = node.getYangLibrary().getUsername();
-            final String yangLigPassword = node.getYangLibrary().getPassword();
-
-            final LibraryModulesSchemas libraryModulesSchemas;
-            if (yangLibURL != null) {
-                if (yangLibUsername != null && yangLigPassword != null) {
-                    libraryModulesSchemas = LibraryModulesSchemas.create(yangLibURL, yangLibUsername, yangLigPassword);
-                } else {
-                    libraryModulesSchemas = LibraryModulesSchemas.create(yangLibURL);
-                }
-
-                for (final Map.Entry<SourceIdentifier, URL> sourceIdentifierURLEntry
-                        : libraryModulesSchemas.getAvailableModels().entrySet()) {
-                    registeredYangLibSources
-                        .add(schemaRegistry.registerSchemaSource(
-                                new YangLibrarySchemaYangSourceProvider(remoteDeviceId,
-                                        libraryModulesSchemas.getAvailableModels()),
-                                PotentialSchemaSource.create(sourceIdentifierURLEntry.getKey(),
-                                        YangTextSchemaSource.class, PotentialSchemaSource.Costs.REMOTE_IO.getValue())));
-                }
-            }
-        }
-
-        final NetconfDevice.SchemaResourcesDTO schemaResourcesDTO = setupSchemaCacheDTO(nodeId, node);
         final RemoteDevice<NetconfSessionPreferences, NetconfMessage, NetconfDeviceCommunicator> device;
         if (node.isSchemaless()) {
             device = new SchemalessNetconfDevice(remoteDeviceId, salFacade);
         } else {
         final RemoteDevice<NetconfSessionPreferences, NetconfMessage, NetconfDeviceCommunicator> device;
         if (node.isSchemaless()) {
             device = new SchemalessNetconfDevice(remoteDeviceId, salFacade);
         } else {
-            NetconfDeviceBuilder netconfDeviceBuilder = new NetconfDeviceBuilder()
-                    .setReconnectOnSchemasChange(reconnectOnChangedSchema)
-                    .setSchemaResourcesDTO(schemaResourcesDTO)
-                    .setGlobalProcessingExecutor(this.processingExecutor)
-                    .setId(remoteDeviceId)
-                    .setSalFacade(salFacade)
-                    .setNode(node)
-                    .setEventExecutor(eventExecutor)
-                    .setNodeOptional(nodeOptional)
-                    .setDeviceActionFactory(deviceActionFactory);
-            device = netconfDeviceBuilder.build();
+            device = createNetconfDevice(remoteDeviceId, salFacade, nodeId, node, nodeOptional);
         }
 
         final Optional<UserPreferences> userCapabilities = getUserCapabilities(node);
         }
 
         final Optional<UserPreferences> userCapabilities = getUserCapabilities(node);
@@ -405,79 +258,63 @@ public abstract class AbstractNetconfTopology implements NetconfTopology {
         return new NetconfConnectorDTO(netconfDeviceCommunicator, salFacade);
     }
 
         return new NetconfConnectorDTO(netconfDeviceCommunicator, salFacade);
     }
 
-    protected NetconfDevice.SchemaResourcesDTO setupSchemaCacheDTO(final NodeId nodeId, final NetconfNode node) {
-        // Setup information related to the SchemaRegistry, SchemaResourceFactory, etc.
-        NetconfDevice.SchemaResourcesDTO schemaResourcesDTO = null;
-        final String moduleSchemaCacheDirectory = node.getSchemaCacheDirectory();
-        // Only checks to ensure the String is not empty or null; further checks related to directory
-        // accessibility and file permissionsare handled during the FilesystemSchemaSourceCache initialization.
-        if (!Strings.isNullOrEmpty(moduleSchemaCacheDirectory)) {
-            // If a custom schema cache directory is specified, create the backing DTO; otherwise,
-            // the SchemaRegistry and SchemaContextFactory remain the default values.
-            if (!moduleSchemaCacheDirectory.equals(DEFAULT_CACHE_DIRECTORY)) {
-                // Multiple modules may be created at once;
-                // synchronize to avoid issues with data consistency among threads.
-                synchronized (SCHEMA_RESOURCES_DTO_MAP) {
-                    // Look for the cached DTO to reuse SchemaRegistry and SchemaContextFactory variables
-                    // if they already exist
-                    schemaResourcesDTO = SCHEMA_RESOURCES_DTO_MAP.get(moduleSchemaCacheDirectory);
-                    if (schemaResourcesDTO == null) {
-                        schemaResourcesDTO = createSchemaResourcesDTO(moduleSchemaCacheDirectory);
-                        schemaResourcesDTO.getSchemaRegistry().registerSchemaSourceListener(
-                                TextToASTTransformer.create((SchemaRepository) schemaResourcesDTO.getSchemaRegistry(),
-                                        schemaResourcesDTO.getSchemaRegistry())
-                        );
-                        SCHEMA_RESOURCES_DTO_MAP.put(moduleSchemaCacheDirectory, schemaResourcesDTO);
-                    }
-                }
-                LOG.info("Netconf connector for device {} will use schema cache directory {} instead of {}",
-                        nodeId.getValue(), moduleSchemaCacheDirectory, DEFAULT_CACHE_DIRECTORY);
-            }
-        } else {
-            LOG.warn("schema-cache-directory for {} is null or empty;  using the default {}",
-                    nodeId.getValue(), QUALIFIED_DEFAULT_CACHE_DIRECTORY);
-        }
+    private NetconfDevice createNetconfDevice(final RemoteDeviceId remoteDeviceId,
+            final RemoteDeviceHandler<NetconfSessionPreferences> salFacade, final NodeId nodeId, final NetconfNode node,
+            final NetconfNodeAugmentedOptional nodeOptional) {
+        final boolean reconnectOnChangedSchema = node.isReconnectOnChangedSchema() == null
+                ? DEFAULT_RECONNECT_ON_CHANGED_SCHEMA : node.isReconnectOnChangedSchema();
 
 
-        if (schemaResourcesDTO == null) {
-            schemaResourcesDTO = new NetconfDevice.SchemaResourcesDTO(schemaRegistry, schemaRepository,
-                    schemaContextFactory, new NetconfStateSchemasResolverImpl());
-        }
+        final SchemaResourcesDTO resources = schemaManager.getSchemaResources(node, nodeId.getValue());
+
+        final NetconfDevice device = new NetconfDeviceBuilder()
+                .setReconnectOnSchemasChange(reconnectOnChangedSchema)
+                .setSchemaResourcesDTO(resources)
+                .setGlobalProcessingExecutor(this.processingExecutor)
+                .setId(remoteDeviceId)
+                .setSalFacade(salFacade)
+                .setNode(node)
+                .setEventExecutor(eventExecutor)
+                .setNodeOptional(nodeOptional)
+                .setDeviceActionFactory(deviceActionFactory)
+                .build();
 
 
-        return schemaResourcesDTO;
-    }
+        final YangLibrary yangLibrary = node.getYangLibrary();
+        if (yangLibrary != null) {
+            final Uri uri = yangLibrary.getYangLibraryUrl();
+            if (uri != null) {
+                // FIXME: NETCONF-675: these registrations need to be torn down with the device. This does not look
+                //                     quite right, though, as we can end up adding a lot of registrations on a
+                //                     per-device basis.
+                //                     This leak is also detected by SpotBugs as soon as this initialization is switched
+                //                     to proper "new ArrayList<>" and hence we really need to attach these somewhere
+                //                     else.
+                //                     It seems we should be subclassing NetconfConnectorDTO for this purpose as a
+                //                     first step and then perhaps do some refcounting or similar based on the
+                //                     schemaRegistry instance.
+                final List<SchemaSourceRegistration<?>> registeredYangLibSources = Lists.newArrayList();
+                final String yangLibURL = uri.getValue();
+                final SchemaSourceRegistry schemaRegistry = resources.getSchemaRegistry();
+
+                // pre register yang library sources as fallback schemas to schema registry
+                final LibraryModulesSchemas schemas;
+                final String yangLibUsername = yangLibrary.getUsername();
+                final String yangLigPassword = yangLibrary.getPassword();
+                if (yangLibUsername != null && yangLigPassword != null) {
+                    schemas = LibraryModulesSchemas.create(yangLibURL, yangLibUsername, yangLigPassword);
+                } else {
+                    schemas = LibraryModulesSchemas.create(yangLibURL);
+                }
 
 
-    /**
-     * Creates the backing Schema classes for a particular directory.
-     *
-     * @param moduleSchemaCacheDirectory The string directory relative to "cache"
-     * @return A DTO containing the Schema classes for the Netconf mount.
-     */
-    private NetconfDevice.SchemaResourcesDTO createSchemaResourcesDTO(final String moduleSchemaCacheDirectory) {
-        final SharedSchemaRepository repository = new SharedSchemaRepository(moduleSchemaCacheDirectory);
-        final EffectiveModelContextFactory contextFactory
-                = repository.createEffectiveModelContextFactory(SchemaContextFactoryConfiguration.getDefault());
-        setSchemaRegistry(repository);
-        setSchemaContextFactory(contextFactory);
-        final FilesystemSchemaSourceCache<YangTextSchemaSource> deviceCache =
-                createDeviceFilesystemCache(moduleSchemaCacheDirectory);
-        repository.registerSchemaSourceListener(deviceCache);
-        repository.registerSchemaSourceListener(
-            InMemorySchemaSourceCache.createSoftCache(repository, ASTSchemaSource.class));
-        return new NetconfDevice.SchemaResourcesDTO(repository, repository, contextFactory,
-                new NetconfStateSchemasResolverImpl());
-    }
+                for (final Map.Entry<SourceIdentifier, URL> entry : schemas.getAvailableModels().entrySet()) {
+                    registeredYangLibSources.add(schemaRegistry.registerSchemaSource(
+                        new YangLibrarySchemaYangSourceProvider(remoteDeviceId, schemas.getAvailableModels()),
+                        PotentialSchemaSource.create(entry.getKey(), YangTextSchemaSource.class,
+                            PotentialSchemaSource.Costs.REMOTE_IO.getValue())));
+                }
+            }
+        }
 
 
-    /**
-     * Creates a <code>FilesystemSchemaSourceCache</code> for the custom schema cache directory.
-     *
-     * @param schemaCacheDirectory The custom cache directory relative to "cache"
-     * @return A <code>FilesystemSchemaSourceCache</code> for the custom schema cache directory
-     */
-    private FilesystemSchemaSourceCache<YangTextSchemaSource> createDeviceFilesystemCache(
-            final String schemaCacheDirectory) {
-        final String relativeSchemaCacheDirectory = CACHE_DIRECTORY + File.separator + schemaCacheDirectory;
-        return new FilesystemSchemaSourceCache<>(schemaRegistry, YangTextSchemaSource.class,
-                new File(relativeSchemaCacheDirectory));
+        return device;
     }
 
     /**
     }
 
     /**
diff --git a/netconf/netconf-topology/src/main/java/org/opendaylight/netconf/topology/spi/SharedSchemaRepositoryProvider.java b/netconf/netconf-topology/src/main/java/org/opendaylight/netconf/topology/spi/SharedSchemaRepositoryProvider.java
deleted file mode 100644 (file)
index 36d0d28..0000000
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * Copyright (c) 2016 Inocybe Technologies and others.  All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-package org.opendaylight.netconf.topology.spi;
-
-import org.eclipse.jdt.annotation.NonNull;
-import org.opendaylight.netconf.topology.api.SchemaRepositoryProvider;
-import org.opendaylight.yangtools.yang.parser.repo.SharedSchemaRepository;
-
-public class SharedSchemaRepositoryProvider implements SchemaRepositoryProvider {
-    private final @NonNull SharedSchemaRepository schemaRepository;
-
-    public SharedSchemaRepositoryProvider(final String moduleName) {
-        schemaRepository = new SharedSchemaRepository(moduleName);
-    }
-
-    @Override
-    public SharedSchemaRepository getSharedSchemaRepository() {
-        return schemaRepository;
-    }
-}
\ No newline at end of file
index 7921f94b63aa02fa0d7d0689c6d1a3d82b9ddd16..58f54729785133d4ba4e3b6cc3fb7b9e6346cb38 100644 (file)
       <groupId>org.slf4j</groupId>
       <artifactId>slf4j-api</artifactId>
     </dependency>
       <groupId>org.slf4j</groupId>
       <artifactId>slf4j-api</artifactId>
     </dependency>
+    <dependency>
+      <groupId>javax.inject</groupId>
+      <artifactId>javax.inject</artifactId>
+      <scope>provided</scope>
+      <optional>true</optional>
+    </dependency>
     <dependency>
       <groupId>org.xmlunit</groupId>
       <artifactId>xmlunit-legacy</artifactId>
     <dependency>
       <groupId>org.xmlunit</groupId>
       <artifactId>xmlunit-legacy</artifactId>
diff --git a/netconf/sal-netconf-connector/src/main/java/org/opendaylight/netconf/sal/connect/api/SchemaResourceManager.java b/netconf/sal-netconf-connector/src/main/java/org/opendaylight/netconf/sal/connect/api/SchemaResourceManager.java
new file mode 100644 (file)
index 0000000..19048d8
--- /dev/null
@@ -0,0 +1,20 @@
+/*
+ * Copyright (c) 2020 PANTHEON.tech, s.r.o. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.netconf.sal.connect.api;
+
+import com.google.common.annotations.Beta;
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.opendaylight.netconf.sal.connect.netconf.NetconfDevice.SchemaResourcesDTO;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.NetconfNode;
+
+@Beta
+@NonNullByDefault
+public interface SchemaResourceManager {
+
+    SchemaResourcesDTO getSchemaResources(NetconfNode node, Object nodeId);
+}
diff --git a/netconf/sal-netconf-connector/src/main/java/org/opendaylight/netconf/sal/connect/impl/DefaultSchemaResourceManager.java b/netconf/sal-netconf-connector/src/main/java/org/opendaylight/netconf/sal/connect/impl/DefaultSchemaResourceManager.java
new file mode 100644 (file)
index 0000000..60f4cf5
--- /dev/null
@@ -0,0 +1,120 @@
+/*
+ * Copyright (c) 2020 PANTHEON.tech, s.r.o. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.netconf.sal.connect.impl;
+
+import static java.util.Objects.requireNonNull;
+
+import com.google.common.annotations.Beta;
+import com.google.common.base.Strings;
+import java.io.File;
+import java.util.HashMap;
+import java.util.Map;
+import javax.inject.Inject;
+import javax.inject.Singleton;
+import org.checkerframework.checker.lock.qual.GuardedBy;
+import org.eclipse.jdt.annotation.NonNull;
+import org.opendaylight.netconf.sal.connect.api.SchemaResourceManager;
+import org.opendaylight.netconf.sal.connect.netconf.NetconfDevice.SchemaResourcesDTO;
+import org.opendaylight.netconf.sal.connect.netconf.NetconfStateSchemasResolverImpl;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.netconf.node.topology.rev150114.NetconfNode;
+import org.opendaylight.yangtools.yang.model.repo.api.SchemaContextFactoryConfiguration;
+import org.opendaylight.yangtools.yang.model.repo.api.YangTextSchemaSource;
+import org.opendaylight.yangtools.yang.model.repo.util.FilesystemSchemaSourceCache;
+import org.opendaylight.yangtools.yang.model.repo.util.InMemorySchemaSourceCache;
+import org.opendaylight.yangtools.yang.parser.repo.SharedSchemaRepository;
+import org.opendaylight.yangtools.yang.parser.rfc7950.repo.ASTSchemaSource;
+import org.opendaylight.yangtools.yang.parser.rfc7950.repo.TextToASTTransformer;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Simple single-node implementation of the {@link SchemaResourceManager} contract. Operates on the specified base
+ * root directory, where a number of independent subdirectories are created, each for a global default and anything
+ * encountered based on configuration.
+ */
+@Beta
+@Singleton
+public final class DefaultSchemaResourceManager implements SchemaResourceManager {
+    private static final Logger LOG = LoggerFactory.getLogger(DefaultSchemaResourceManager.class);
+
+    @GuardedBy("this")
+    private final Map<String, SchemaResourcesDTO> resources = new HashMap<>();
+    private final @NonNull SchemaResourcesDTO defaultResources;
+    private final String defaultSubdirectory;
+    private final String rootDirectory;
+
+    @Inject
+    public DefaultSchemaResourceManager() {
+        this("cache", "schema");
+    }
+
+    public DefaultSchemaResourceManager(final String rootDirectory, final String defaultSubdirectory) {
+        this.rootDirectory = requireNonNull(rootDirectory);
+        this.defaultSubdirectory = requireNonNull(defaultSubdirectory);
+        this.defaultResources = createResources(defaultSubdirectory);
+    }
+
+    @Override
+    public SchemaResourcesDTO getSchemaResources(final NetconfNode node, final Object nodeId) {
+        final String subdir = node.getSchemaCacheDirectory();
+        if (defaultSubdirectory.equals(subdir)) {
+            // Fast path for default devices
+            return defaultResources;
+        }
+        if (Strings.isNullOrEmpty(subdir)) {
+            // FIXME: we probably want to change semantics here:
+            //        - update model to not allow empty name
+            //        - silently default to the default
+            LOG.warn("schema-cache-directory for {} is null or empty;  using the default {}", nodeId,
+                defaultSubdirectory);
+            return defaultResources;
+        }
+
+        LOG.info("Netconf connector for device {} will use schema cache directory {} instead of {}", nodeId, subdir,
+            defaultSubdirectory);
+        return getSchemaResources(subdir);
+    }
+
+    private synchronized @NonNull SchemaResourcesDTO getSchemaResources(final String subdir) {
+        // Fast path for unusual devices
+        final SchemaResourcesDTO existing = resources.get(subdir);
+        if (existing != null) {
+            return existing;
+        }
+
+        final SchemaResourcesDTO created = createResources(subdir);
+        resources.put(subdir, created);
+        return created;
+    }
+
+    private @NonNull SchemaResourcesDTO createResources(final String subdir) {
+        // Setup the baseline empty registry
+        // FIXME: add YangParserFactory argument
+        final SharedSchemaRepository repository = new SharedSchemaRepository(subdir);
+
+        // Teach the registry how to transform YANG text to ASTSchemaSource internally
+        repository.registerSchemaSourceListener(TextToASTTransformer.create(repository, repository));
+
+        // Attach a soft cache of ASTSchemaSource instances. This is important during convergence when we are fishing
+        // for a consistent set of modules, as it skips the need to re-parse the text sources multiple times. It also
+        // helps establishing different sets of contexts, as they can share this pre-made cache.
+        repository.registerSchemaSourceListener(
+            // FIXME: add knobs to control cache lifetime explicitly
+            InMemorySchemaSourceCache.createSoftCache(repository, ASTSchemaSource.class));
+
+        // Attach the filesystem cache, providing persistence capability, so that restarts do not require us to
+        // re-populate the cache. This also acts as a side-load capability, as anything pre-populated into that
+        // directory will not be fetched from the device.
+        repository.registerSchemaSourceListener(new FilesystemSchemaSourceCache<>(repository,
+                YangTextSchemaSource.class, new File(rootDirectory + File.separator + subdir)));
+
+        return new SchemaResourcesDTO(repository, repository,
+            repository.createEffectiveModelContextFactory(SchemaContextFactoryConfiguration.getDefault()),
+            new NetconfStateSchemasResolverImpl());
+    }
+}
index 6916c588fefc3de837991b03e5b040209e1d851d..d21a6d7291edd087590ced5b0c09cf6a26bb8c9b 100644 (file)
@@ -18,4 +18,11 @@ and is available at http://www.eclipse.org/legal/epl-v10.html
     <service ref="deviceActionFactory"
              interface="org.opendaylight.netconf.sal.connect.api.DeviceActionFactory"
              odl:type="default"/>
     <service ref="deviceActionFactory"
              interface="org.opendaylight.netconf.sal.connect.api.DeviceActionFactory"
              odl:type="default"/>
+
+    <bean id="schemaResourceManager"
+          class="org.opendaylight.netconf.sal.connect.impl.DefaultSchemaResourceManager">
+    </bean>
+
+    <service ref="schemaResourceManager"
+             interface="org.opendaylight.netconf.sal.connect.api.SchemaResourceManager"/>
 </blueprint>
\ No newline at end of file
 </blueprint>
\ No newline at end of file