Delete subfolder of a Watcher ends the loop

1

My code is as follows:

try {
        watcher = FileSystems.getDefault().newWatchService();
        registerAll(path);
    } catch (IOException e) {
        return;
    }

    while (true){
        WatchKey key;
        try {
            key = watcher.take();
        } catch (InterruptedException x) {
            return;
        }
        for (WatchEvent<?> event: key.pollEvents()) {
            WatchEvent.Kind<?> kind = event.kind();

            if (kind == OVERFLOW) {
                continue;
            }

            WatchEvent<Path> ev = (WatchEvent<Path>)event;
            Path filename = ev.context();
            Path dir = (Path)key.watchable();
            Path child = dir.resolve(filename);
            File file = child.toFile();

            System.out.println(kind + " | " + file);

            if(kind == ENTRY_CREATE && file.isDirectory()){
                register(file);//transforma file em path e registra
            }
        }

        boolean valid = key.reset();
        if (!valid) {
            break;
        }
    }

The problem is that when a subfolder is deleted, it counts as overflow (when I use debug the kind is overflow at the time) and the key.reset ends up being invalid, and the loop ends.

    
asked by anonymous 02.03.2016 / 19:45

1 answer

1

According to the comments, you are monitoring the subdirectories recursively.

However, the Standard WatcherService API supports monitoring one directory at a time, and to monitor multiple directories you need to make multiple calls.

So you probably have some code that goes through the directory structure adding the watcher recursively in each subdirectory, as in example below:

private void registerAll(final Path start) throws IOException {
    // register directory and sub-directories
    Files.walkFileTree(start, new SimpleFileVisitor<Path>() {
        @Override
        public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs)
            throws IOException
        {
            register(dir);
            return FileVisitResult.CONTINUE;
        }
    });
}

If this is true, it means that your loop is receiving events from all directories.

Normally, the loop terminates if the directory is deleted, so it is expected behavior that you describe in the question.

On the other hand, since you want to continue monitoring the others, you need an additional logic, that is, a control to just exit the loop and run break in case the main directory is removed.

In the example that I mentioned so, this is done by adding each directory monitored to a map and then the loop is closed only when it is verified that there is no directory being monitored.

The snippet that does this in the example is this:

boolean valid = key.reset();
if (!valid) {
    keys.remove(key);

    // all directories are inaccessible
    if (keys.isEmpty()) {
        break;
    }
}
    
03.03.2016 / 04:25