Add BasicWithKeyFileAttributeView interface

This new interface is similar to `BasicFileAttributeView` except it
gives implementations a hint that the fileKey() should be acquired
even at some performance cost.

`FileTreeWalker` uses this new interface to request a file key
in addition to regular file attributes so that file equality can
be efficiently performed when checking for loops during file
tree traversal.

This makes `FileTreeWalker` about 2x faster when traversing non
trivial file system trees with the FOLLOW_LINKS option.

Change-Id: I8de047c8fc241dbab9ad57c5e361118a3a94893d

(AKA JBR-3680 Cherry-pick Google's NIO patches to get faster file listing)

(cherry picked from commit 6d1c3f06c4)
This commit is contained in:
Renaud Paquay
2020-02-19 12:06:27 -08:00
committed by jbrbot
parent dd214bb9e0
commit 5a5c47be97
5 changed files with 79 additions and 1 deletions

View File

@@ -25,6 +25,8 @@
package java.nio.file;
import java.nio.file.attribute.BasicFileAttributeView;
import java.nio.file.attribute.BasicWithKeyFileAttributeView;
import java.nio.file.attribute.BasicFileAttributes;
import java.io.Closeable;
import java.io.IOException;
@@ -217,7 +219,11 @@ class FileTreeWalker implements Closeable {
// links then a link target might not exist so get attributes of link
BasicFileAttributes attrs;
try {
attrs = Files.readAttributes(file, BasicFileAttributes.class, linkOptions);
BasicFileAttributeView view = Files.getFileAttributeView(file, BasicWithKeyFileAttributeView.class, linkOptions);
if (view == null) {
view = Files.getFileAttributeView(file, BasicFileAttributeView.class, linkOptions);
}
attrs = view.readAttributes();
} catch (IOException ioe) {
if (!followLinks)
throw ioe;

View File

@@ -0,0 +1,38 @@
/*
* Copyright (c) 2007, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package java.nio.file.attribute;
import java.io.IOException;
/**
* Similar to {@link BasicFileAttributeView} with a hint to implementors
* to retrieve a valid {@link BasicFileAttributes#fileKey()} if possible, even
* at a performance cost.
*/
public interface BasicWithKeyFileAttributeView
extends BasicFileAttributeView {
}

View File

@@ -148,6 +148,23 @@ class WindowsFileAttributeViews {
}
}
private static class BasicWithKey extends Basic {
BasicWithKey(WindowsPath file, boolean followLinks) {
super(file, followLinks);
}
@Override
public WindowsFileAttributes readAttributes() throws IOException {
file.checkRead();
try {
return WindowsFileAttributes.getWithFileKey(file, followLinks);
} catch (WindowsException x) {
x.rethrowAsIOException(file);
return null; // keep compiler happy
}
}
}
static class Dos extends Basic implements DosFileAttributeView {
private static final String READONLY_NAME = "readonly";
private static final String ARCHIVE_NAME = "archive";
@@ -287,6 +304,10 @@ class WindowsFileAttributeViews {
return new Basic(file, followLinks);
}
static Basic createBasicWithKeyView(WindowsPath file, boolean followLinks) {
return new BasicWithKey(file, followLinks);
}
static Dos createDosView(WindowsPath file, boolean followLinks) {
return new Dos(file, followLinks);
}

View File

@@ -334,6 +334,15 @@ class WindowsFileAttributes
}
// file is reparse point so need to open file to get attributes
return getWithFileKey(path, followLinks);
}
/**
* Returns attributes of given file.
*/
static WindowsFileAttributes getWithFileKey(WindowsPath path, boolean followLinks)
throws WindowsException
{
long handle = path.openForReadAttributeAccess(followLinks);
try {
return readAttributes(handle);

View File

@@ -166,6 +166,8 @@ class WindowsFileSystemProvider
boolean followLinks = Util.followLinks(options);
if (view == BasicFileAttributeView.class)
return (V) WindowsFileAttributeViews.createBasicView(file, followLinks);
if (view == BasicWithKeyFileAttributeView.class)
return (V) WindowsFileAttributeViews.createBasicWithKeyView(file, followLinks);
if (view == DosFileAttributeView.class)
return (V) WindowsFileAttributeViews.createDosView(file, followLinks);
if (view == AclFileAttributeView.class)
@@ -203,6 +205,8 @@ class WindowsFileSystemProvider
boolean followLinks = Util.followLinks(options);
if (name.equals("basic"))
return WindowsFileAttributeViews.createBasicView(file, followLinks);
if (name.equals("basicwithkey"))
return WindowsFileAttributeViews.createBasicWithKeyView(file, followLinks);
if (name.equals("dos"))
return WindowsFileAttributeViews.createDosView(file, followLinks);
if (name.equals("acl"))