提交 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;
import hudson.FilePath;
import hudson.Util;
import hudson.remoting.Callable;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
......@@ -34,10 +35,8 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.IdentityHashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.StringTokenizer;
import java.util.logging.Level;
import java.util.logging.Logger;
......@@ -252,7 +251,7 @@ public final class DirectoryBrowserSupport implements HttpResponse {
} else
if(serveDirIndex) {
// serve directory index
glob = buildChildPaths(baseFile, req.getLocale());
glob = baseFile.run(new BuildChildPaths(baseFile, req.getLocale()));
}
if(glob!=null) {
......@@ -431,7 +430,6 @@ public final class DirectoryBrowserSupport implements HttpResponse {
private static final class FileComparator implements Comparator<VirtualFile> {
private Collator collator;
private final Map<VirtualFile,Boolean> isDirCache = new IdentityHashMap<VirtualFile,Boolean>();
FileComparator(Locale locale) {
this.collator = Collator.getInstance(locale);
......@@ -445,18 +443,9 @@ public final class DirectoryBrowserSupport implements HttpResponse {
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) {
try {
if(isDirectory(f)) return 0;
if(f.isDirectory()) return 0;
else return 1;
} catch (IOException ex) {
return 0;
......@@ -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
* list of {@link Path} represents one child item to be shown
......
......@@ -26,6 +26,7 @@ package jenkins.util;
import hudson.FilePath;
import hudson.model.DirectoryBrowserSupport;
import hudson.remoting.Callable;
import hudson.remoting.Channel;
import hudson.remoting.VirtualChannel;
import hudson.util.DirScanner;
......@@ -34,6 +35,7 @@ import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.Serializable;
import java.net.URI;
import java.util.ArrayList;
import java.util.List;
......@@ -56,7 +58,7 @@ import javax.annotation.Nonnull;
* @see FilePath
* @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
......@@ -184,13 +186,34 @@ public abstract class VirtualFile implements Comparable<VirtualFile> {
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.
* @param f a disk file (need not exist)
* @return a wrapper
*/
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() {
return f.getName();
}
......@@ -238,7 +261,6 @@ public abstract class VirtualFile implements Comparable<VirtualFile> {
@Override public InputStream open() throws IOException {
return new FileInputStream(f);
}
};
}
/**
......@@ -247,7 +269,13 @@ public abstract class VirtualFile implements Comparable<VirtualFile> {
* @return a wrapper
*/
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() {
return f.getName();
}
......@@ -328,7 +356,13 @@ public abstract class VirtualFile implements Comparable<VirtualFile> {
@Override public InputStream open() throws IOException {
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 final String glob;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册