From df4b23f57306ef4acf0c85481d8f3b7a5ea39b7c Mon Sep 17 00:00:00 2001 From: Cheryl King Date: Fri, 20 Oct 2023 13:54:25 -0500 Subject: [PATCH 1/2] Fix for dev mode file watching problem --- .../tools/common/plugins/util/DevUtil.java | 57 +++++++++++++++---- 1 file changed, 47 insertions(+), 10 deletions(-) diff --git a/src/main/java/io/openliberty/tools/common/plugins/util/DevUtil.java b/src/main/java/io/openliberty/tools/common/plugins/util/DevUtil.java index b299d154..222a5bb6 100644 --- a/src/main/java/io/openliberty/tools/common/plugins/util/DevUtil.java +++ b/src/main/java/io/openliberty/tools/common/plugins/util/DevUtil.java @@ -88,6 +88,7 @@ import org.apache.commons.io.filefilter.NameFileFilter; import org.apache.commons.io.filefilter.TrueFileFilter; import org.apache.commons.io.input.CloseShieldInputStream; +import org.apache.commons.io.monitor.FileAlterationListener; import org.apache.commons.io.monitor.FileAlterationListenerAdaptor; import org.apache.commons.io.monitor.FileAlterationObserver; import org.w3c.dom.Document; @@ -3246,7 +3247,7 @@ private void registerSingleFile(final File registerFile, final ThreadPoolExecuto * @throws IOException unable to read the canonical path name */ private void registerSingleFile(final File registerFile, final ThreadPoolExecutor executor, boolean removeOnContainerRebuild) throws IOException { - if (trackingMode == FileTrackMode.POLLING || trackingMode == FileTrackMode.NOT_SET) { + if (trackingMode == FileTrackMode.POLLING || trackingMode == FileTrackMode.NOT_SET) { String parentPath = registerFile.getParentFile().getCanonicalPath(); debug("Registering single file polling for " + registerFile.toString()); @@ -3257,11 +3258,18 @@ private void registerSingleFile(final File registerFile, final ThreadPoolExecuto tempCombinedObservers.addAll(fileObservers); tempCombinedObservers.addAll(newFileObservers); + FileAlterationObserver existingObserver = null; + // if this path is already observed, ignore it for (FileAlterationObserver observer : tempCombinedObservers) { if (parentPath.equals(observer.getDirectory().getCanonicalPath())) { - debug("Skipping single file polling for " + registerFile.toString() + " since its parent directory is already being observed"); - return; + debug("Updating file polling for " + registerFile.toString() + " since its parent directory is already being observed"); + existingObserver = observer; + if (fileObservers.contains(existingObserver)) { + debug("Found existing observer in fileObservers"); + } else if (newFileObservers.contains(existingObserver)) { + debug("Found existing observer in newFileObservers"); + } } } @@ -3282,17 +3290,24 @@ public boolean accept(File file) { }; try { - debug("Adding single file observer for: " + registerFile.toString()); - FileAlterationObserver observer = addFileAlterationObserver(executor, parentPath, singleFileFilter); + FileAlterationObserver observer = existingObserver; + if (observer != null) { + debug("Updating parent file observer for: " + registerFile.toString()); + observer = addFileAlterationObserver(executor, observer, parentPath, singleFileFilter); + } else { + debug("Adding single file observer for: " + registerFile.toString()); + observer = addFileAlterationObserver(executor, parentPath, singleFileFilter); + } if (removeOnContainerRebuild) { - debug("Adding file to containerfileDirectoriesFileObservers: " + registerFile.toString()); - containerfileDirectoriesFileObservers.add(observer); + debug("Adding file to containerfileDirectoriesFileObservers: " + registerFile.toString()); + containerfileDirectoriesFileObservers.add(observer); } } catch (Exception e) { error("Could not observe single file " + registerFile.toString(), e); } } } + if (trackingMode == FileTrackMode.FILE_WATCHER || trackingMode == FileTrackMode.NOT_SET) { debug("Adding directory to WatchService " + registerFile.getParentFile().toPath() + " for single file " + registerFile.getName()); WatchKey key = registerFile.getParentFile().toPath().register( @@ -3307,6 +3322,21 @@ public boolean accept(File file) { } } + private FileAlterationObserver addFileAlterationObserver(final ThreadPoolExecutor executor, FileAlterationObserver observer, String parentPath, FileFilter filter) + throws Exception { + FileAlterationObserver newObserver = getFileAlterationObserver(executor, parentPath, filter); + for (FileAlterationListener nextListener: observer.getListeners()) { + newObserver.addListener(nextListener); + } + newObserver.initialize(); + // clean up old existing observer + fileObservers.remove(observer); + newFileObservers.remove(observer); + // add new observer with the combined listeners + newFileObservers.add(newObserver); + return newObserver; + } + private FileAlterationObserver addFileAlterationObserver(final ThreadPoolExecutor executor, String parentPath, FileFilter filter) throws Exception { FileAlterationObserver observer = getFileAlterationObserver(executor, parentPath, filter); @@ -3315,8 +3345,13 @@ private FileAlterationObserver addFileAlterationObserver(final ThreadPoolExecuto return observer; } - private FileAlterationObserver getFileAlterationObserver(final ThreadPoolExecutor executor, final String parentPath, FileFilter filter) { + private FileAlterationObserver getFileAlterationObserver(final ThreadPoolExecutor executor, final String parentPath, FileFilter filter) throws Exception { FileAlterationObserver observer = new FileAlterationObserver(parentPath, filter); + addFileAlterationListener(executor, observer, parentPath, filter); + return observer; + } + + private void addFileAlterationListener(final ThreadPoolExecutor executor, FileAlterationObserver observer, final String parentPath, FileFilter filter) { observer.addListener(new FileAlterationListenerAdaptor() { @Override public void onDirectoryCreate(File file) { @@ -3354,18 +3389,21 @@ private void onAlteration(final ThreadPoolExecutor executor, final String parent try { WatchKey wk = null; if (watcher != null) { - wk = watcher.poll(100, TimeUnit.MILLISECONDS); + // use bigger timeout on first file change to determine FILE_WATCHER vs POLLING (issue 1741) + wk = watcher.poll(1000, TimeUnit.MILLISECONDS); } List> events = null; if (wk != null) { events = wk.pollEvents(); } if ((events == null) || events.isEmpty()) { + debug("Setting file track mode to POLLING since no file watcher events were found."); trackingMode = FileTrackMode.POLLING; if (watcher != null) { watcher.close(); } } else { + debug("Setting file track mode to FILE_WATCHER."); trackingMode = FileTrackMode.FILE_WATCHER; disablePolling(); } @@ -3381,7 +3419,6 @@ private void onAlteration(final ThreadPoolExecutor executor, final String parent } } }); - return observer; } /** From 82bc11a3038104e7179fa42867633fe162563cce Mon Sep 17 00:00:00 2001 From: Cheryl King Date: Fri, 20 Oct 2023 14:34:25 -0500 Subject: [PATCH 2/2] cleanup --- .../tools/common/plugins/util/DevUtil.java | 21 +++++++++++-------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/src/main/java/io/openliberty/tools/common/plugins/util/DevUtil.java b/src/main/java/io/openliberty/tools/common/plugins/util/DevUtil.java index 222a5bb6..c1b9d1cb 100644 --- a/src/main/java/io/openliberty/tools/common/plugins/util/DevUtil.java +++ b/src/main/java/io/openliberty/tools/common/plugins/util/DevUtil.java @@ -3247,7 +3247,7 @@ private void registerSingleFile(final File registerFile, final ThreadPoolExecuto * @throws IOException unable to read the canonical path name */ private void registerSingleFile(final File registerFile, final ThreadPoolExecutor executor, boolean removeOnContainerRebuild) throws IOException { - if (trackingMode == FileTrackMode.POLLING || trackingMode == FileTrackMode.NOT_SET) { + if (trackingMode == FileTrackMode.POLLING || trackingMode == FileTrackMode.NOT_SET) { String parentPath = registerFile.getParentFile().getCanonicalPath(); debug("Registering single file polling for " + registerFile.toString()); @@ -3265,11 +3265,6 @@ private void registerSingleFile(final File registerFile, final ThreadPoolExecuto if (parentPath.equals(observer.getDirectory().getCanonicalPath())) { debug("Updating file polling for " + registerFile.toString() + " since its parent directory is already being observed"); existingObserver = observer; - if (fileObservers.contains(existingObserver)) { - debug("Found existing observer in fileObservers"); - } else if (newFileObservers.contains(existingObserver)) { - debug("Found existing observer in newFileObservers"); - } } } @@ -3299,8 +3294,8 @@ public boolean accept(File file) { observer = addFileAlterationObserver(executor, parentPath, singleFileFilter); } if (removeOnContainerRebuild) { - debug("Adding file to containerfileDirectoriesFileObservers: " + registerFile.toString()); - containerfileDirectoriesFileObservers.add(observer); + debug("Adding file to containerfileDirectoriesFileObservers: " + registerFile.toString()); + containerfileDirectoriesFileObservers.add(observer); } } catch (Exception e) { error("Could not observe single file " + registerFile.toString(), e); @@ -3324,14 +3319,22 @@ public boolean accept(File file) { private FileAlterationObserver addFileAlterationObserver(final ThreadPoolExecutor executor, FileAlterationObserver observer, String parentPath, FileFilter filter) throws Exception { + // create new observer for filter FileAlterationObserver newObserver = getFileAlterationObserver(executor, parentPath, filter); + // iterate through existing listeners on observer and add them to newObserver for (FileAlterationListener nextListener: observer.getListeners()) { newObserver.addListener(nextListener); } newObserver.initialize(); - // clean up old existing observer + // clean up previous observer fileObservers.remove(observer); newFileObservers.remove(observer); + try { + // destroy the observer + observer.destroy(); + } catch (Exception e) { + debug("Could not destroy file observer", e); + } // add new observer with the combined listeners newFileObservers.add(newObserver); return newObserver;