BUG-6857: ConfigLoader rework 05/47505/5
authorClaudio D. Gasparini <cgaspari@cisco.com>
Tue, 25 Oct 2016 11:22:22 +0000 (13:22 +0200)
committerClaudio D. Gasparini <cgaspari@cisco.com>
Wed, 26 Oct 2016 08:22:23 +0000 (08:22 +0000)
ConfigLoader rework. Split Watchservice.

Change-Id: If0a07f03b3f923d940eb0c8dc31acc691870cb0b
Signed-off-by: Claudio D. Gasparini <cgaspari@cisco.com>
bgp/config-loader-impl/src/main/java/org/opendaylight/protocol/bgp/config/loader/impl/BGPFileWatcher.java [new file with mode: 0644]
bgp/config-loader-impl/src/main/java/org/opendaylight/protocol/bgp/config/loader/impl/ConfigLoaderImpl.java
bgp/config-loader-impl/src/main/java/org/opendaylight/protocol/bgp/config/loader/impl/FileWatcher.java [new file with mode: 0644]
bgp/config-loader-impl/src/main/resources/org/opendaylight/blueprint/bgp-config-loader.xml
bgp/config-loader-spi/src/main/java/org/opendaylight/protocol/bgp/config/loader/spi/ConfigFileProcessor.java
bgp/config-loader-spi/src/main/java/org/opendaylight/protocol/bgp/config/loader/spi/ConfigLoader.java

diff --git a/bgp/config-loader-impl/src/main/java/org/opendaylight/protocol/bgp/config/loader/impl/BGPFileWatcher.java b/bgp/config-loader-impl/src/main/java/org/opendaylight/protocol/bgp/config/loader/impl/BGPFileWatcher.java
new file mode 100644 (file)
index 0000000..8760717
--- /dev/null
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2016 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.protocol.bgp.config.loader.impl;
+
+import static java.nio.file.StandardWatchEventKinds.ENTRY_CREATE;
+import static java.nio.file.StandardWatchEventKinds.OVERFLOW;
+
+import java.io.File;
+import java.io.IOException;
+import java.nio.file.FileSystems;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.nio.file.WatchService;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public final class BGPFileWatcher implements FileWatcher, AutoCloseable {
+    private static final Logger LOG = LoggerFactory.getLogger(BGPFileWatcher.class);
+    private static final String INTERRUPTED = "InterruptedException";
+    private static final String DEFAULT_APP_CONFIG_FILE_PATH = "etc" + File.separator + "opendaylight" + File.separator + "bgp";
+    private static final Path PATH = Paths.get(DEFAULT_APP_CONFIG_FILE_PATH);
+    private final WatchService watchService;
+
+    public BGPFileWatcher() throws IOException {
+        this.watchService = FileSystems.getDefault().newWatchService();
+        Runtime.getRuntime().addShutdownHook(new Thread() {
+            @Override
+            public void run() {
+                try {
+                    BGPFileWatcher.this.watchService.close();
+                } catch (final IOException e) {
+                    LOG.warn(INTERRUPTED, e);
+                }
+            }
+        });
+        PATH.register(this.watchService, OVERFLOW, ENTRY_CREATE);
+    }
+
+    @Override
+    public String getPathFile() {
+        return DEFAULT_APP_CONFIG_FILE_PATH;
+    }
+
+    @Override
+    public WatchService getWatchService() {
+        return this.watchService;
+    }
+
+    @Override
+    public synchronized void close() throws Exception {
+        if (this.watchService != null) {
+            this.watchService.close();
+        }
+    }
+}
index 677ec5f3c8ef15fbededb6ebc41dd4b9280ca254..fd2ef5e36e01aceb48f509b7402d8322ce77d79b 100644 (file)
@@ -8,23 +8,16 @@
 
 package org.opendaylight.protocol.bgp.config.loader.impl;
 
-import static java.nio.file.StandardWatchEventKinds.ENTRY_CREATE;
-import static java.nio.file.StandardWatchEventKinds.OVERFLOW;
-
 import com.google.common.base.Preconditions;
 import java.io.File;
 import java.io.FileInputStream;
-import java.io.IOException;
 import java.io.InputStream;
-import java.nio.file.FileSystems;
-import java.nio.file.Path;
-import java.nio.file.Paths;
+import java.nio.file.WatchEvent;
 import java.nio.file.WatchKey;
 import java.nio.file.WatchService;
 import java.util.HashMap;
 import java.util.Map;
 import java.util.regex.Pattern;
-import javax.annotation.Nonnull;
 import javax.annotation.concurrent.GuardedBy;
 import javax.xml.stream.XMLInputFactory;
 import javax.xml.stream.XMLStreamReader;
@@ -38,63 +31,54 @@ import org.opendaylight.yangtools.yang.data.codec.xml.XmlParserStream;
 import org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNormalizedNodeStreamWriter;
 import org.opendaylight.yangtools.yang.data.impl.schema.NormalizedNodeResult;
 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+import org.opendaylight.yangtools.yang.model.api.SchemaNode;
 import org.opendaylight.yangtools.yang.model.util.SchemaContextUtil;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 public final class ConfigLoaderImpl implements ConfigLoader, AutoCloseable {
     private static final Logger LOG = LoggerFactory.getLogger(ConfigLoaderImpl.class);
-    private static final String DEFAULT_APP_CONFIG_FILE_PATH = "etc" + File.separator + "opendaylight" + File.separator + "bgp";
     private static final String INTERRUPTED = "InterruptedException";
     private static final String EXTENSION = "-.*\\.xml";
     private static final String INITIAL = "^";
-    private static final Path PATH = Paths.get(DEFAULT_APP_CONFIG_FILE_PATH);
     @GuardedBy("this")
     private final Map<String, ConfigFileProcessor> configServices = new HashMap<>();
     private final SchemaContext schemaContext;
-    private final Thread watcherThread;
     private final BindingNormalizedNodeSerializer bindingSerializer;
+    private final String path;
+    private final Thread watcherThread;
 
-    public ConfigLoaderImpl(final SchemaContext schemaContext, final BindingNormalizedNodeSerializer bindingSerializer) {
+    public ConfigLoaderImpl(final SchemaContext schemaContext, final BindingNormalizedNodeSerializer bindingSerializer,
+        final String path, final WatchService watchService) {
         this.schemaContext = Preconditions.checkNotNull(schemaContext);
         this.bindingSerializer = Preconditions.checkNotNull(bindingSerializer);
-        this.watcherThread = new Thread(new Watcher());
-        this.watcherThread.start();
-        LOG.info("Config Loader service initiated");
-    }
-
-    private class Watcher implements Runnable {
-        @Override
-        public void run() {
-            WatchKey key;
+        this.path = Preconditions.checkNotNull(path);
+        Preconditions.checkNotNull(watchService);
+        this.watcherThread = new Thread(() -> {
             try {
                 while (!Thread.currentThread().isInterrupted()) {
-                    final WatchService watcher = FileSystems.getDefault().newWatchService();
-                    Runtime.getRuntime().addShutdownHook(new Thread() {
-                        @Override
-                        public void run() {
-                            try {
-                                watcher.close();
-                            } catch (final IOException e) {
-                                LOG.warn(INTERRUPTED, e);
+                    try {
+                        final WatchKey key = watchService.take();
+                        if (key != null) {
+                            for (final WatchEvent event : key.pollEvents()) {
+                                handleEvent(event.context().toString());
+                            }
+                            final boolean reset = key.reset();
+                            if (!reset) {
+                                LOG.warn("Could not reset the watch key.");
+                                return;
                             }
                         }
-                    });
-
-                    PATH.register(watcher, OVERFLOW, ENTRY_CREATE);
-                    key = watcher.take();
-                    key.pollEvents().forEach(event -> handleEvent(event.context().toString()));
-
-                    final boolean reset = key.reset();
-                    if (!reset) {
-                        LOG.warn("Could not reset the watch key.");
-                        break;
+                    } catch (final InterruptedException e) {
+                        LOG.warn(INTERRUPTED, e);
                     }
                 }
             } catch (final Exception e) {
                 LOG.warn(INTERRUPTED, e);
             }
-        }
+        });
+        this.watcherThread.start();
+        LOG.info("Config Loader service initiated");
     }
 
     private void handleConfigFile(final ConfigFileProcessor config, final String filename) {
@@ -113,22 +97,23 @@ public final class ConfigLoaderImpl implements ConfigLoader, AutoCloseable {
         final NormalizedNodeResult result = new NormalizedNodeResult();
         final NormalizedNodeStreamWriter streamWriter = ImmutableNormalizedNodeStreamWriter.from(result);
 
-        final InputStream resourceAsStream = new FileInputStream(new File(DEFAULT_APP_CONFIG_FILE_PATH, filename));
+        final InputStream resourceAsStream = new FileInputStream(new File(this.path, filename));
         final XMLInputFactory factory = XMLInputFactory.newInstance();
         final XMLStreamReader reader = factory.createXMLStreamReader(resourceAsStream);
 
-        final XmlParserStream xmlParser = XmlParserStream.create(streamWriter, this.schemaContext,
-            SchemaContextUtil.findDataSchemaNode(this.schemaContext, config.getSchemaPath()));
+        final SchemaNode schemaNode = SchemaContextUtil.findDataSchemaNode(this.schemaContext, config.getSchemaPath());
+        final XmlParserStream xmlParser = XmlParserStream.create(streamWriter, this.schemaContext, schemaNode);
         xmlParser.parse(reader);
 
         return result.getResult();
     }
 
-    public synchronized AbstractRegistration registerConfigFile(@Nonnull final ConfigFileProcessor config) {
+    @Override
+    public synchronized AbstractRegistration registerConfigFile(final ConfigFileProcessor config) {
         final String pattern = INITIAL + config.getSchemaPath().getLastComponent().getLocalName() + EXTENSION;
-        configServices.put(pattern, config);
+        this.configServices.put(pattern, config);
 
-        final File[] fList = new File(DEFAULT_APP_CONFIG_FILE_PATH).listFiles();
+        final File[] fList = new File(this.path).listFiles();
         if (fList != null) {
             for (final File file : fList) {
                 if (file.isFile()) {
@@ -156,7 +141,7 @@ public final class ConfigLoaderImpl implements ConfigLoader, AutoCloseable {
     }
 
     private synchronized void handleEvent(final String filename) {
-        configServices.entrySet().stream().filter(entry -> Pattern.matches(entry.getKey(), filename)).
+        this.configServices.entrySet().stream().filter(entry -> Pattern.matches(entry.getKey(), filename)).
             forEach(entry -> handleConfigFile(entry.getValue(), filename));
     }
 
diff --git a/bgp/config-loader-impl/src/main/java/org/opendaylight/protocol/bgp/config/loader/impl/FileWatcher.java b/bgp/config-loader-impl/src/main/java/org/opendaylight/protocol/bgp/config/loader/impl/FileWatcher.java
new file mode 100644 (file)
index 0000000..c852ede
--- /dev/null
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2016 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.protocol.bgp.config.loader.impl;
+
+import java.nio.file.WatchService;
+import javax.annotation.Nonnull;
+
+public interface FileWatcher {
+    /**
+     * Path Folder watched
+     *
+     * @return Path
+     */
+    @Nonnull
+    String getPathFile();
+
+    /**
+     * Return WatchService
+     *
+     * @return WatchService
+     */
+    @Nonnull
+    WatchService getWatchService();
+}
index 8c456a65af5a070eb96f47a49b21cd33afab61b1..1c818c8e70ce9438c3c216e47c97143eb48d0d9c 100644 (file)
     <odl:static-reference id="schemaService" interface="org.opendaylight.controller.sal.core.api.model.SchemaService" />
     <odl:static-reference id="binding-codec" interface="org.opendaylight.yangtools.binding.data.codec.api.BindingNormalizedNodeSerializer" />
 
+    <bean id="bgpFileWatcher" class="org.opendaylight.protocol.bgp.config.loader.impl.BGPFileWatcher"  destroy-method="close" />
+
     <bean id="bgpConfigLoader" class="org.opendaylight.protocol.bgp.config.loader.impl.ConfigLoaderImpl"  destroy-method="close">
         <argument>
             <bean factory-ref="schemaService" factory-method="getGlobalContext"/>
         </argument>
         <argument ref="binding-codec"/>
+        <argument>
+            <bean factory-ref="bgpFileWatcher" factory-method="getPathFile"/>
+        </argument>
+        <argument>
+            <bean factory-ref="bgpFileWatcher" factory-method="getWatchService"/>
+        </argument>
     </bean>
 
     <service ref="bgpConfigLoader" interface="org.opendaylight.protocol.bgp.config.loader.spi.ConfigLoader" odl:type="default"/>
index a764c1a1b0e7e4f423c19ad0694882ae4ba35eb9..d8c5935b091270521d1cfb3d24a73bc34b987dd1 100644 (file)
@@ -24,7 +24,7 @@ public interface ConfigFileProcessor {
      *
      * @return SchemaPath
      */
-    SchemaPath getSchemaPath();
+    @Nonnull SchemaPath getSchemaPath();
 
     /**
      * Load the information contained on the normalized node
index c88091a2e248c900ca42e8e59c380aedee94c0f2..b13d9f1fa7dcd2e30183cd79051269143603c10f 100644 (file)
@@ -17,11 +17,11 @@ public interface ConfigLoader {
      * Register object model handler
      * @param config Config File Processor
      */
-    AbstractRegistration registerConfigFile(@Nonnull ConfigFileProcessor config);
+    @Nonnull AbstractRegistration registerConfigFile(@Nonnull ConfigFileProcessor config);
 
     /**
      *
      * @return Binding Normalized node serializer
      */
-    BindingNormalizedNodeSerializer getBindingNormalizedNodeSerializer();
+    @Nonnull BindingNormalizedNodeSerializer getBindingNormalizedNodeSerializer();
 }