Deleting a Watcher’s subfolder ends the loop

Asked

Viewed 36 times

1

My code is this::

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 Kind is overflow on time) and the key.reset ends up being invalid, and the loop ends.

  • You are logging the Watcher for the subdirectories as well?

  • yes, that’s right. registerAll does it, and it’s working ! the bad and the time it deletes

1 answer

1


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

However, the API of Watcherservice standard 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 adds the Watcher recursively in each subdirectory, as in example down 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 ends if the directory is deleted, so it is expected behavior what you describe in the question.

On the other hand, as you want to continue monitoring the other necessary ones, it is necessary an additional logic, that is, a control to only exit the loop and run the break in case the main directory is removed.

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

The passage 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;
    }
}

Browser other questions tagged

You are not signed in. Login or sign up in order to post.