Make OvsdbConnectionService instance-only 75/72875/3
authorStephen Kitt <skitt@redhat.com>
Tue, 12 Jun 2018 09:01:58 +0000 (11:01 +0200)
committerVishal Thapar <vthapar@redhat.com>
Sat, 16 Jun 2018 05:27:12 +0000 (05:27 +0000)
This patch ensures that the volatile data managed by
OvsdbConnectionService is stored per instance, and it removes the
static initialiser and all non-BluePrint instantiations. Other library
users can still create their own instances if necessary, but the
library code will no longer create multiple instances by default,
ensuring that BluePrint-mediated configuration changes are applied.

Change-Id: I41ca0c679d68e7dfeba3b5fd503194180358a9a2
JIRA: OVSDB-465
Signed-off-by: Stephen Kitt <skitt@redhat.com>
hwvtepsouthbound/hwvtepsouthbound-impl/src/main/java/org/opendaylight/ovsdb/hwvtepsouthbound/HwvtepConnectionManager.java
hwvtepsouthbound/hwvtepsouthbound-impl/src/main/java/org/opendaylight/ovsdb/hwvtepsouthbound/HwvtepSouthboundProvider.java
library/impl/src/main/java/org/opendaylight/ovsdb/lib/impl/OvsdbConnectionService.java
library/impl/src/main/java/org/opendaylight/ovsdb/lib/jsonrpc/ExceptionHandler.java
library/impl/src/main/resources/org/opendaylight/blueprint/library.xml
southbound/southbound-impl/src/test/java/org/opendaylight/ovsdb/southbound/OvsdbConnectionManagerTest.java

index 8a7514aa43864c8f5fcdb78b01f011b98e9c520c..567389a39d0015cd3b22a999e0729ef5c7973677 100644 (file)
@@ -48,8 +48,8 @@ import org.opendaylight.ovsdb.hwvtepsouthbound.transact.DependencyQueue;
 import org.opendaylight.ovsdb.hwvtepsouthbound.transactions.md.HwvtepGlobalRemoveCommand;
 import org.opendaylight.ovsdb.hwvtepsouthbound.transactions.md.TransactionInvoker;
 import org.opendaylight.ovsdb.lib.OvsdbClient;
+import org.opendaylight.ovsdb.lib.OvsdbConnection;
 import org.opendaylight.ovsdb.lib.OvsdbConnectionListener;
-import org.opendaylight.ovsdb.lib.impl.OvsdbConnectionService;
 import org.opendaylight.ovsdb.lib.operations.Operation;
 import org.opendaylight.ovsdb.lib.operations.OperationResult;
 import org.opendaylight.ovsdb.lib.operations.Select;
@@ -88,15 +88,17 @@ public class HwvtepConnectionManager implements OvsdbConnectionListener, AutoClo
     private final HwvtepOperGlobalListener hwvtepOperGlobalListener;
     private final Map<InstanceIdentifier<Node>, TransactionHistory> controllerTxHistory = new ConcurrentHashMap<>();
     private final Map<InstanceIdentifier<Node>, TransactionHistory> deviceUpdateHistory = new ConcurrentHashMap<>();
+    private final OvsdbConnection ovsdbConnectionService;
 
     public HwvtepConnectionManager(DataBroker db, TransactionInvoker txInvoker,
-                    EntityOwnershipService entityOwnershipService) {
+                    EntityOwnershipService entityOwnershipService, OvsdbConnection ovsdbConnectionService) {
         this.db = db;
         this.txInvoker = txInvoker;
         this.entityOwnershipService = entityOwnershipService;
         this.hwvtepDeviceEntityOwnershipListener = new HwvtepDeviceEntityOwnershipListener(this,entityOwnershipService);
         this.reconciliationManager = new ReconciliationManager(db);
         this.hwvtepOperGlobalListener = new HwvtepOperGlobalListener(db, this);
+        this.ovsdbConnectionService = ovsdbConnectionService;
     }
 
     @Override
@@ -177,7 +179,7 @@ public class HwvtepConnectionManager implements OvsdbConnectionListener, AutoClo
                                HwvtepGlobalAugmentation hwvtepGlobal) throws UnknownHostException, ConnectException {
         LOG.info("Connecting to {}", HwvtepSouthboundUtil.connectionInfoToString(hwvtepGlobal.getConnectionInfo()));
         InetAddress ip = HwvtepSouthboundMapper.createInetAddress(hwvtepGlobal.getConnectionInfo().getRemoteIp());
-        OvsdbClient client = OvsdbConnectionService.getService()
+        OvsdbClient client = ovsdbConnectionService
                         .connect(ip, hwvtepGlobal.getConnectionInfo().getRemotePort().getValue());
         if (client != null) {
             putInstanceIdentifier(hwvtepGlobal.getConnectionInfo(), iid.firstIdentifierOf(Node.class));
index 76b742a95cae787973bce876ed306cb853da246c..bf6d2707bc6fd26b9ff46f52ff314ddf393de5e9 100644 (file)
@@ -79,7 +79,7 @@ public class HwvtepSouthboundProvider implements ClusteredDataTreeChangeListener
     public void init() {
         LOG.info("HwvtepSouthboundProvider Session Initiated");
         txInvoker = new TransactionInvokerImpl(dataBroker);
-        cm = new HwvtepConnectionManager(dataBroker, txInvoker, entityOwnershipService);
+        cm = new HwvtepConnectionManager(dataBroker, txInvoker, entityOwnershipService, ovsdbConnection);
         hwvtepDTListener = new HwvtepDataChangeListener(dataBroker, cm);
         hwvtepReconciliationManager = new HwvtepReconciliationManager(dataBroker, cm);
         //Register listener for entityOnwership changes
index 375f2f863a7ab3215623ee75ce89a1ffd872811a..cca48636a2e3af151f824802b86f653e3cb8e7b1 100644 (file)
@@ -15,7 +15,6 @@ 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.ThreadFactoryBuilder;
-import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
 import io.netty.bootstrap.Bootstrap;
 import io.netty.bootstrap.ServerBootstrap;
 import io.netty.channel.AdaptiveRecvByteBufAllocator;
@@ -84,7 +83,6 @@ import org.slf4j.LoggerFactory;
  * environment. Hence a single instance of the service will be active (via Service Registry in OSGi)
  * and a Singleton object in a non-OSGi environment.
  */
-@SuppressFBWarnings("ST_WRITE_TO_STATIC_FROM_INSTANCE_METHOD")
 public class OvsdbConnectionService implements AutoCloseable, OvsdbConnection {
     private static final Logger LOG = LoggerFactory.getLogger(OvsdbConnectionService.class);
     private static final int IDLE_READER_TIMEOUT = 30;
@@ -102,25 +100,19 @@ public class OvsdbConnectionService implements AutoCloseable, OvsdbConnection {
     private static final StalePassiveConnectionService STALE_PASSIVE_CONNECTION_SERVICE =
             new StalePassiveConnectionService(EXECUTOR_SERVICE);
 
-    private static final OvsdbConnection CONNECTION_SERVICE = new OvsdbConnectionService();
-
     private static final Set<OvsdbConnectionListener> CONNECTION_LISTENERS = ConcurrentHashMap.newKeySet();
     private static final Map<OvsdbClient, Channel> CONNECTIONS = new ConcurrentHashMap<>();
 
-    private static volatile boolean useSSL = false;
-    private static volatile ICertificateManager certManagerSrv;
+    private volatile boolean useSSL = false;
+    private volatile ICertificateManager certManagerSrv;
 
-    private static volatile int jsonRpcDecoderMaxFrameLength = 100000;
-    private static volatile Channel serverChannel;
+    private volatile int jsonRpcDecoderMaxFrameLength = 100000;
+    private volatile Channel serverChannel;
 
     private final AtomicBoolean singletonCreated = new AtomicBoolean(false);
     private volatile String listenerIp = "0.0.0.0";
     private volatile int listenerPort = 6640;
 
-    public static OvsdbConnection getService() {
-        return CONNECTION_SERVICE;
-    }
-
     /**
      * If the SSL flag is enabled, the method internally will establish TLS communication using the default
      * ODL certificateManager SSLContext and attributes.
@@ -165,7 +157,7 @@ public class OvsdbConnectionService implements AutoCloseable, OvsdbConnection {
                             new StringEncoder(CharsetUtil.UTF_8),
                             new IdleStateHandler(IDLE_READER_TIMEOUT, 0, 0),
                             new ReadTimeoutHandler(READ_TIMEOUT),
-                            new ExceptionHandler());
+                            new ExceptionHandler(OvsdbConnectionService.this));
                 }
             });
 
@@ -291,7 +283,7 @@ public class OvsdbConnectionService implements AutoCloseable, OvsdbConnection {
      * If the SSL flag is enabled, the method internally will establish TLS communication using the default
      * ODL certificateManager SSLContext and attributes.
      */
-    private static void ovsdbManager(String ip, int port) {
+    private void ovsdbManager(String ip, int port) {
         if (useSSL) {
             if (certManagerSrv == null) {
                 LOG.error("Certificate Manager service is not available cannot establish the SSL communication.");
@@ -308,7 +300,7 @@ public class OvsdbConnectionService implements AutoCloseable, OvsdbConnection {
      * OVSDB Passive listening thread that uses Netty ServerBootstrap to open
      * passive connection with Ssl and handle channel callbacks.
      */
-    private static void ovsdbManagerWithSsl(String ip, int port, final ICertificateManager certificateManagerSrv,
+    private void ovsdbManagerWithSsl(String ip, int port, final ICertificateManager certificateManagerSrv,
                                             final String[] protocols, final String[] cipherSuites) {
         EventLoopGroup bossGroup = new NioEventLoopGroup();
         EventLoopGroup workerGroup = new NioEventLoopGroup();
@@ -350,7 +342,7 @@ public class OvsdbConnectionService implements AutoCloseable, OvsdbConnection {
                                  new StringEncoder(CharsetUtil.UTF_8),
                                  new IdleStateHandler(IDLE_READER_TIMEOUT, 0, 0),
                                  new ReadTimeoutHandler(READ_TIMEOUT),
-                                 new ExceptionHandler());
+                                 new ExceptionHandler(OvsdbConnectionService.this));
 
                             handleNewPassiveConnection(channel);
                         }
index 8ce4b6b62527797b1678cbbfbd37f08dba792f55..69709c3c220e5ded45e54f99fb468f8aea49717e 100644 (file)
@@ -17,8 +17,8 @@ import io.netty.handler.timeout.IdleStateEvent;
 import io.netty.handler.timeout.ReadTimeoutException;
 import java.io.IOException;
 import org.opendaylight.ovsdb.lib.OvsdbClient;
+import org.opendaylight.ovsdb.lib.OvsdbConnection;
 import org.opendaylight.ovsdb.lib.error.InvalidEncodingException;
-import org.opendaylight.ovsdb.lib.impl.OvsdbConnectionService;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -26,8 +26,14 @@ public class ExceptionHandler extends ChannelDuplexHandler {
 
     private static final Logger LOG = LoggerFactory.getLogger(ExceptionHandler.class);
 
+    private final OvsdbConnection ovsdbConnectionService;
+
+    public ExceptionHandler(OvsdbConnection ovsdbConnectionService) {
+        this.ovsdbConnectionService = ovsdbConnectionService;
+    }
+
     @Override
-    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
+    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
         if (ctx.channel().isActive()) {
             LOG.error("Exception occurred while processing connection pipeline", cause);
             if ((cause instanceof InvalidEncodingException)
@@ -53,15 +59,14 @@ public class ExceptionHandler extends ChannelDuplexHandler {
     }
 
     @Override
-    public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
+    public void userEventTriggered(ChannelHandlerContext ctx, Object evt) {
         if (evt instanceof IdleStateEvent) {
             LOG.debug("Get idle state event");
             IdleStateEvent event = (IdleStateEvent) evt;
             if (event.state() == IdleState.READER_IDLE) {
                 LOG.debug("Reader idle state. Send echo message to peer");
                 //Send echo message to peer
-                OvsdbClient client =
-                             OvsdbConnectionService.getService().getClient(ctx.channel());
+                OvsdbClient client = ovsdbConnectionService.getClient(ctx.channel());
                 client.echo();
             }
         }
index d23f2148639f53f09e04b09610bf6b5c42c7426a..40073a087e20bcd2c7e9b14aa2a81e7d75670ba8 100644 (file)
         interface="org.opendaylight.aaa.cert.api.ICertificateManager"
         odl:type="default-certificate-manager"/>
 
-  <bean id="library" class="org.opendaylight.ovsdb.lib.impl.OvsdbConnectionService">
+  <!-- Notify OvsdbConnectionService with any change in the config properties value-->
+  <bean id="ovsdbConnectionService" class="org.opendaylight.ovsdb.lib.impl.OvsdbConnectionService">
+    <cm:managed-properties persistent-id="org.opendaylight.ovsdb.library"
+                           update-strategy="component-managed"
+                           update-method="updateConfigParameter"/>
     <property name="ovsdbListenerIp" value="${ovsdb-listener-ip}"/>
     <property name="ovsdbListenerPort" value="${ovsdb-listener-port}"/>
     <property name="ovsdbRpcTaskTimeout" value="${ovsdb-rpc-task-timeout}"/>
     <property name="jsonRpcDecoderMaxFrameLength" value="${json-rpc-decoder-max-frame-length}"/>
   </bean>
 
-  <!-- Notify OvsdbConnectionService with any change in the config properties value-->
-  <bean id="ovsdbConnectionService" class="org.opendaylight.ovsdb.lib.impl.OvsdbConnectionService">
-    <cm:managed-properties persistent-id="org.opendaylight.ovsdb.library"
-                           update-strategy="component-managed"
-                           update-method="updateConfigParameter"/>
-     <property name="certificatManager" ref="aaaCertificateManager"/>
-  </bean>
-
   <service ref="ovsdbConnectionService" interface="org.opendaylight.ovsdb.lib.OvsdbConnection"
     odl:type="default" />
 
index e90daca48499c0cb3a1abbe2434536a74b37a781..a5c51861e0013d3a69ea634257430c0c187122ff 100644 (file)
@@ -329,7 +329,7 @@ public class OvsdbConnectionManagerTest {
         when(SouthboundMapper.createInetAddress(any(IpAddress.class))).thenReturn(ip);
 
         PowerMockito.mockStatic(OvsdbConnectionService.class);
-        when(OvsdbConnectionService.getService()).thenReturn(ovsdbConnection);
+//        when(OvsdbConnectionService.getService()).thenReturn(ovsdbConnection);
         PortNumber port = mock(PortNumber.class);
         when(connectionInfo.getRemotePort()).thenReturn(port);
         when(port.getValue()).thenReturn(8080);