2

Java's java.nio.file.Files.walkFileTree() executes the visitor's visitFile() method even if a file doesn't exist (a recently-deleted file).

FileUtils.forceDelete(certainFile);
Files.exists(certainFile.toPath()); // Returns false, as expected
MySimpleFileVisitor visitor = new MySimpleFileVisitor(); // Extends SimpleFileVisitor. All it does is override visitFile() so I can see that it visits the deleted file.
Files.walkFileTree(directory, visitor); // Calls visitor.visitFile on certainFile. Not expected!

Is this possible? I am using Windows, and the file is on a network drive.

Files.walkFileTree() calls FileTreeWalker.walk(), which calls Files.newDirectoryStream(). The only explanation I can think of is that Files.newDirectoryStream returns a DirectoryStream that includes the deleted file.

Andrew Liu
  • 309
  • 1
  • 2
  • 13
  • Perhaps it is related to caching (the directory info) of the network (SMB?) file-system .. I suspect that it is part of the underlying subsystem itself (eg. even Windows Explorer is "delayed") and not Java. – user2864740 Aug 21 '14 at 21:11
  • Can you show your full code? – afzalex Aug 21 '14 at 21:15
  • @afzalex: Unfortunately, I can't show more code, even though I know that limits people from helping me. – Andrew Liu Aug 22 '14 at 01:28

2 Answers2

4

Yes, it is possible.

Let us assume that the Files.walk… methods all use DirectoryStreams to walk the file tree (which, at least as of Java 1.8.0_05, they in fact do) or an internal equivalent. The documentation for DirectoryStream says:

The iterator is weakly consistent. It is thread safe but does not freeze the directory while iterating, so it may (or may not) reflect updates to the directory that occur after the DirectoryStream is created.

VGR
  • 33,718
  • 4
  • 37
  • 50
  • I saw that documentation as well, but wasn't sure exactly how it applies to this particular behavior. It is helpful to hear that such behavior is possible. – Andrew Liu Aug 25 '14 at 12:40
  • I am removing this as the accepted answer because it explains why the iterator is weakly consistent, but it does not explain why, when the DirectoryStream is created, it already thinks that certainFile exists. – Andrew Liu Aug 26 '14 at 16:58
  • Are you certain the DirectoryStream was created after your file was deleted? How recent is "recently-deleted"? – VGR Aug 26 '14 at 18:40
  • "Recently-deleted" really means what I have in the code sample, i.e., _very_ recent. I delete the file, check it is deleted, then immediately call Files.walkFileTree, which calls newDirectoryStream. I'm assuming that (1) Files.exists() returns false if and only if the file is truly deleted, (2) Files.newDirectoryStream creates a new DirectoryStream without relying on some cached DirectoryStream. Given these assumptions, I deduce that DirectoryStream must be created after the file was deleted. – Andrew Liu Aug 26 '14 at 22:57
  • Do you get different results if you replace `FileUtils.forceDelete` with [Files.delete](http://docs.oracle.com/javase/8/docs/api/java/nio/file/Files.html#delete-java.nio.file.Path-) or [Files.deleteIfExists](http://docs.oracle.com/javase/8/docs/api/java/nio/file/Files.html#deleteIfExists-java.nio.file.Path-)? – VGR Aug 27 '14 at 02:29
  • That's a good question---I don't know. I would like to try it. The problem is that I can no longer reproduce the issue (which is partly why I asked the original question). So, if I can reproduce the issue consistently, I will keep this option in mind. – Andrew Liu Aug 27 '14 at 11:47
  • Also, FileUtils.forceDelete automatically does a recursive delete. If I use Files.delete, then I would need to use a FileVisitor. – Andrew Liu Aug 27 '14 at 11:48
4

Yes, it is possible. In my case, the following conditions had to be met to reproduce the failure:

  1. The file of interest exists in a folder that is indexed by Windows.
  2. The file's type has a Windows Property Handler associated with it.
  3. Windows has time to start indexing the file before it is deleted.
  4. The property handler takes a long time (a few minutes) to release its hold on the file.

I just discovered all of this information, which is why none of it is mentioned in the original question.

Andrew Liu
  • 309
  • 1
  • 2
  • 13