提交 6fe5d6c6 编写于 作者: J Jesse Glick

[JENKINS-21780] Much more effective fix.

Introduce VirtualFile.run method to batch together commands.
This should restore pre-ArtifactManager performance for workspace browsing.
上级 e51fdbbc
...@@ -25,6 +25,7 @@ package hudson.model; ...@@ -25,6 +25,7 @@ package hudson.model;
import hudson.FilePath; import hudson.FilePath;
import hudson.Util; import hudson.Util;
import hudson.remoting.Callable;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.OutputStream; import java.io.OutputStream;
...@@ -34,10 +35,8 @@ import java.util.ArrayList; ...@@ -34,10 +35,8 @@ import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collections; import java.util.Collections;
import java.util.Comparator; import java.util.Comparator;
import java.util.IdentityHashMap;
import java.util.List; import java.util.List;
import java.util.Locale; import java.util.Locale;
import java.util.Map;
import java.util.StringTokenizer; import java.util.StringTokenizer;
import java.util.logging.Level; import java.util.logging.Level;
import java.util.logging.Logger; import java.util.logging.Logger;
...@@ -252,7 +251,7 @@ public final class DirectoryBrowserSupport implements HttpResponse { ...@@ -252,7 +251,7 @@ public final class DirectoryBrowserSupport implements HttpResponse {
} else } else
if(serveDirIndex) { if(serveDirIndex) {
// serve directory index // serve directory index
glob = buildChildPaths(baseFile, req.getLocale()); glob = baseFile.run(new BuildChildPaths(baseFile, req.getLocale()));
} }
if(glob!=null) { if(glob!=null) {
...@@ -431,7 +430,6 @@ public final class DirectoryBrowserSupport implements HttpResponse { ...@@ -431,7 +430,6 @@ public final class DirectoryBrowserSupport implements HttpResponse {
private static final class FileComparator implements Comparator<VirtualFile> { private static final class FileComparator implements Comparator<VirtualFile> {
private Collator collator; private Collator collator;
private final Map<VirtualFile,Boolean> isDirCache = new IdentityHashMap<VirtualFile,Boolean>();
FileComparator(Locale locale) { FileComparator(Locale locale) {
this.collator = Collator.getInstance(locale); this.collator = Collator.getInstance(locale);
...@@ -445,18 +443,9 @@ public final class DirectoryBrowserSupport implements HttpResponse { ...@@ -445,18 +443,9 @@ public final class DirectoryBrowserSupport implements HttpResponse {
return this.collator.compare(lhs.getName(), rhs.getName()); return this.collator.compare(lhs.getName(), rhs.getName());
} }
private boolean isDirectory(VirtualFile f) throws IOException {
Boolean known = isDirCache.get(f);
if (known == null) {
known = f.isDirectory();
isDirCache.put(f, known);
}
return known;
}
private int dirRank(VirtualFile f) { private int dirRank(VirtualFile f) {
try { try {
if(isDirectory(f)) return 0; if(f.isDirectory()) return 0;
else return 1; else return 1;
} catch (IOException ex) { } catch (IOException ex) {
return 0; return 0;
...@@ -464,6 +453,17 @@ public final class DirectoryBrowserSupport implements HttpResponse { ...@@ -464,6 +453,17 @@ public final class DirectoryBrowserSupport implements HttpResponse {
} }
} }
private static final class BuildChildPaths implements Callable<List<List<Path>>,IOException> {
private final VirtualFile cur;
private final Locale locale;
BuildChildPaths(VirtualFile cur, Locale locale) {
this.cur = cur;
this.locale = locale;
}
@Override public List<List<Path>> call() throws IOException {
return buildChildPaths(cur, locale);
}
}
/** /**
* Builds a list of list of {@link Path}. The inner * Builds a list of list of {@link Path}. The inner
* list of {@link Path} represents one child item to be shown * list of {@link Path} represents one child item to be shown
......
...@@ -26,6 +26,7 @@ package jenkins.util; ...@@ -26,6 +26,7 @@ package jenkins.util;
import hudson.FilePath; import hudson.FilePath;
import hudson.model.DirectoryBrowserSupport; import hudson.model.DirectoryBrowserSupport;
import hudson.remoting.Callable;
import hudson.remoting.Channel; import hudson.remoting.Channel;
import hudson.remoting.VirtualChannel; import hudson.remoting.VirtualChannel;
import hudson.util.DirScanner; import hudson.util.DirScanner;
...@@ -34,6 +35,7 @@ import java.io.File; ...@@ -34,6 +35,7 @@ import java.io.File;
import java.io.FileInputStream; import java.io.FileInputStream;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.Serializable;
import java.net.URI; import java.net.URI;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
...@@ -56,7 +58,7 @@ import javax.annotation.Nonnull; ...@@ -56,7 +58,7 @@ import javax.annotation.Nonnull;
* @see FilePath * @see FilePath
* @since 1.532 * @since 1.532
*/ */
public abstract class VirtualFile implements Comparable<VirtualFile> { public abstract class VirtualFile implements Comparable<VirtualFile>, Serializable {
/** /**
* Gets the base name, meaning just the last portion of the path name without any * Gets the base name, meaning just the last portion of the path name without any
...@@ -184,13 +186,34 @@ public abstract class VirtualFile implements Comparable<VirtualFile> { ...@@ -184,13 +186,34 @@ public abstract class VirtualFile implements Comparable<VirtualFile> {
return toURI().toString(); return toURI().toString();
} }
/**
* Does some calculations in batch.
* For a remote file, this can be much faster than doing the corresponding operations one by one as separate requests.
* The default implementation just calls the block directly.
* @param <V> a value type
* @param <T> the exception type
* @param callable something to run all at once (only helpful if any mentioned files are on the same system)
* @return the callable result
* @throws IOException if remote communication failed
* @since 1.554
*/
public <V> V run(Callable<V,IOException> callable) throws IOException {
return callable.call();
}
/** /**
* Creates a virtual file wrapper for a local file. * Creates a virtual file wrapper for a local file.
* @param f a disk file (need not exist) * @param f a disk file (need not exist)
* @return a wrapper * @return a wrapper
*/ */
public static VirtualFile forFile(final File f) { public static VirtualFile forFile(final File f) {
return new VirtualFile() { return new FileVF(f);
}
private static final class FileVF extends VirtualFile {
private final File f;
FileVF(File f) {
this.f = f;
}
@Override public String getName() { @Override public String getName() {
return f.getName(); return f.getName();
} }
...@@ -238,7 +261,6 @@ public abstract class VirtualFile implements Comparable<VirtualFile> { ...@@ -238,7 +261,6 @@ public abstract class VirtualFile implements Comparable<VirtualFile> {
@Override public InputStream open() throws IOException { @Override public InputStream open() throws IOException {
return new FileInputStream(f); return new FileInputStream(f);
} }
};
} }
/** /**
...@@ -247,7 +269,13 @@ public abstract class VirtualFile implements Comparable<VirtualFile> { ...@@ -247,7 +269,13 @@ public abstract class VirtualFile implements Comparable<VirtualFile> {
* @return a wrapper * @return a wrapper
*/ */
public static VirtualFile forFilePath(final FilePath f) { public static VirtualFile forFilePath(final FilePath f) {
return new VirtualFile() { return new FilePathVF(f);
}
private static final class FilePathVF extends VirtualFile {
private final FilePath f;
FilePathVF(FilePath f) {
this.f = f;
}
@Override public String getName() { @Override public String getName() {
return f.getName(); return f.getName();
} }
...@@ -328,7 +356,13 @@ public abstract class VirtualFile implements Comparable<VirtualFile> { ...@@ -328,7 +356,13 @@ public abstract class VirtualFile implements Comparable<VirtualFile> {
@Override public InputStream open() throws IOException { @Override public InputStream open() throws IOException {
return f.read(); return f.read();
} }
}; @Override public <V> V run(Callable<V,IOException> callable) throws IOException {
try {
return f.act(callable);
} catch (InterruptedException x) {
throw (IOException) new IOException(x.toString()).initCause(x);
}
}
} }
private static final class Scanner implements FilePath.FileCallable<String[]> { private static final class Scanner implements FilePath.FileCallable<String[]> {
private final String glob; private final String glob;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册