diff --git a/changelog.html b/changelog.html
index e20c5644f6e6..f3772de41cf7 100644
--- a/changelog.html
+++ b/changelog.html
@@ -61,6 +61,9 @@
Better robustness against XML deserialization errors.
(issue 21024)
+
+ Minimizing disk I/O while loading the names of build records during Jenkins startup.
+ (issue 21078)
Avoiding serializing the owning build as part of a test result action, as this can lead to errors later.
(issue 18410)
diff --git a/core/src/main/java/hudson/model/RunMap.java b/core/src/main/java/hudson/model/RunMap.java
index 7afdabbfbce2..a7aa1921241a 100644
--- a/core/src/main/java/hudson/model/RunMap.java
+++ b/core/src/main/java/hudson/model/RunMap.java
@@ -194,24 +194,21 @@ protected FilenameFilter createDirectoryFilter() {
final SimpleDateFormat formatter = Run.ID_FORMATTER.get();
return new FilenameFilter() {
- public boolean accept(File dir, String name) {
- // JENKINS-1461 sometimes create bogus data directories with impossible dates, such as year 0, April 31st,
- // or August 0th. Date object doesn't roundtrip those, so we eventually fail to load this data.
- // Don't even bother trying.
- if (!isCorrectDate(name)) {
- LOGGER.log(FINE, "Skipping {0}", new File(dir,name));
+ @Override public boolean accept(File dir, String name) {
+ if (name.startsWith("0000")) {
+ // JENKINS-1461 sometimes create bogus data directories with impossible dates, such as year 0, April 31st,
+ // or August 0th. Date object doesn't roundtrip those, so we eventually fail to load this data.
+ // Don't even bother trying.
return false;
}
- return !name.startsWith("0000") && new File(dir,name).isDirectory();
- }
-
- private boolean isCorrectDate(String name) {
try {
- if(formatter.format(formatter.parse(name)).equals(name))
+ if (formatter.format(formatter.parse(name)).equals(name)) {
return true;
+ }
} catch (ParseException e) {
// fall through
}
+ LOGGER.log(FINE, "Skipping {0} in {1}", new Object[] {name, dir});
return false;
}
};
diff --git a/core/src/main/java/jenkins/model/lazy/AbstractLazyLoadRunMap.java b/core/src/main/java/jenkins/model/lazy/AbstractLazyLoadRunMap.java
index 92561a23a4c3..a0c50a67a3a2 100644
--- a/core/src/main/java/jenkins/model/lazy/AbstractLazyLoadRunMap.java
+++ b/core/src/main/java/jenkins/model/lazy/AbstractLazyLoadRunMap.java
@@ -26,19 +26,15 @@
import hudson.model.Job;
import hudson.model.Run;
import hudson.model.RunMap;
-import org.apache.commons.collections.keyvalue.DefaultMapEntry;
-import org.kohsuke.accmod.Restricted;
-import org.kohsuke.accmod.restrictions.NoExternalUse;
-
import java.io.File;
import java.io.FilenameFilter;
import java.io.IOException;
import java.lang.ref.Reference;
import java.util.AbstractMap;
import java.util.ArrayList;
-import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
+import java.util.List;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.Set;
@@ -50,6 +46,9 @@
import static jenkins.model.lazy.AbstractLazyLoadRunMap.Direction.*;
import static jenkins.model.lazy.Boundary.*;
+import org.apache.commons.collections.keyvalue.DefaultMapEntry;
+import org.kohsuke.accmod.Restricted;
+import org.kohsuke.accmod.restrictions.NoExternalUse;
/**
* {@link SortedMap} that keeps build records by their build numbers, in the descending order
@@ -224,26 +223,27 @@ public void purgeCache() {
}
private void loadIdOnDisk() {
- String[] buildDirs = dir.list(createDirectoryFilter());
- if (buildDirs==null) {
+ String[] kids = dir.list();
+ if (kids == null) {
// the job may have just been created
- buildDirs=EMPTY_STRING_ARRAY;
+ kids = EMPTY_STRING_ARRAY;
}
- // wrap into ArrayList to enable mutation
- Arrays.sort(buildDirs);
- idOnDisk = new SortedList(new ArrayList(Arrays.asList(buildDirs)));
-
- // TODO: should we check that shortcuts is a symlink?
- String[] shortcuts = dir.list();
- if (shortcuts==null) shortcuts=EMPTY_STRING_ARRAY;
- SortedIntList list = new SortedIntList(shortcuts.length/2);
- for (String s : shortcuts) {
- try {
- list.add(Integer.parseInt(s));
- } catch (NumberFormatException e) {
- // this isn't a shortcut
+ List buildDirs = new ArrayList();
+ FilenameFilter buildDirFilter = createDirectoryFilter();
+ SortedIntList list = new SortedIntList(kids.length / 2);
+ for (String s : kids) {
+ if (buildDirFilter.accept(dir, s)) {
+ buildDirs.add(s);
+ } else {
+ try {
+ list.add(Integer.parseInt(s));
+ } catch (NumberFormatException e) {
+ // this isn't a shortcut
+ }
}
}
+ Collections.sort(buildDirs);
+ idOnDisk = new SortedList(buildDirs);
list.sort();
numberOnDisk = list;
}