Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java nio FileSystem Watcher locks directories. Deletion becomes impossible [duplicate]

I'm using the new feature of Java7 for watching directories for changes (as it is described in the following tutorial: http://download.oracle.com/javase/tutorial/essential/io/notification.html )

The watching itself works (nearly) without problems.

More or less I have two issues and I hope some of you have an idea how to handle it.

  1. After a folder is added to watch, the VM has access to it and it doesn't release it. This should not be such a big issue. But if you're creating a directory in another directory and in this one more. (e.g. you create in directory c:\tmp\a the directory b and in b the directory c (c:\tmp\a\b\c)) it is not possible to delete the directory a, because of the access of the VM to b and c. If you want to delete all of the folders (e.g., with your Windows Explorer) you have to delete c first, then b and then a. It's strange, but this way works (though is inconvenient)

  2. This issue seems to be a result of the first one. If many changes in a occur sometimes (more or less) I get an exception which tells me, the newly created folder is used by another process and it is not possible to access it. It's strange, because I think this should not matter to get a notification. And because it is not completely clear when exactly this exception is thrown.

Do you have an idea how to make it possible to not have the lock or at least to let the user the ability to delete such a directory structure in the classical convenient way?

like image 217
Mariano Avatar asked Nov 13 '11 03:11

Mariano


1 Answers

Well I've tried the code showcased in the link you posted, doing the same things you're trying to do:

In my c:\temp directory I create programatically a c:\temp\a dir and then a c:\temp\a\b directory:

File startDir = new File("c:\temp");
        if(!startDir.exists()) {
            startDir.mkdir();
        }
        File aDir = new File("c:\\temp\\a");
        File bDir = new File("c:\\temp\\a\\b");
        if(!aDir.exists()) {
            aDir.mkdir();
        }
        if(!bDir.exists()) {
            bDir.mkdir();
        }

Then I add watchers to the "a" and "b" directories:

public static void watch(final File dir,final WatchService watcher) {
        Path path = dir.toPath();
        try {
            final WatchKey bDirWatchKey = path.register(watcher, StandardWatchEventKinds.ENTRY_MODIFY);
            new Thread(new Runnable() {
                public void run() {
                    System.out.println("Watching: "+dir.getName());
                    while(true) {
                        try {Thread.sleep(1000);} catch (InterruptedException e) {}
                        List<WatchEvent<?>> events = bDirWatchKey.pollEvents();
                        for(WatchEvent<?> event:events) {
                            System.out.println(dir.getName()+" event: #"+event.count()+","+event.kind()+" File="+event.context());
                        }
                    }                   
                }
            }).start();
        } catch (IOException x) {
            x.printStackTrace();
        }
    }

This works ok, if I modify files in "a" or "b" I get the corresponding console output.

It's true that with Windows Explorer (on a Windowx XP machine) I cannot delete a watched directory (it tells me I don't have access rights). I can however delete it with other tools such as Total Commander. I can even delete then from the Windows command line with rd c:\temp\a\b. I think this is more of an issue with Windows Explorer than with Java...

like image 103
Shivan Dragon Avatar answered Sep 20 '22 19:09

Shivan Dragon