提交 7790dbca 编写于 作者: J Jesse Glick

[FIXED JENKINS-19515] Try to avoid truncation of fingerprint storage files.

1. Use AtomicFileWriter on the hypothesis that an exception during save() caused truncation.
2. Improve logging from the cleanup thread since that may be related to the root cause.
3. Regardless of the cause, recover more gracefully by deleting any truncated file rather than throwing the error up.
上级 89a11462
......@@ -67,6 +67,9 @@ Upcoming changes</a>
<li class=bug>
Since 1.518, fingerprint serialization broke when job or file names contained XML special characters like ampersands.
(<a href="https://issues.jenkins-ci.org/browse/JENKINS-18337">issue 18337</a>)
<li class=bug>
Robustness against truncated fingerprint files.
(<a href="https://issues.jenkins-ci.org/browse/JENKINS-19515">issue 19515</a>)
<li class=rfe>
JavaScript error in the checkUrl computation shouldn't break the job configuration page.
(<a href="https://issues.jenkins-ci.org/browse/JENKINS-19457">issue 19457</a>)
......
......@@ -38,11 +38,13 @@ import hudson.BulkChange;
import hudson.Extension;
import hudson.model.listeners.ItemListener;
import hudson.model.listeners.SaveableListener;
import hudson.util.AtomicFileWriter;
import hudson.util.HexBinaryConverter;
import hudson.util.Iterators;
import hudson.util.PersistedList;
import hudson.util.RunList;
import hudson.util.XStream2;
import java.io.EOFException;
import jenkins.model.FingerprintFacet;
import jenkins.model.Jenkins;
import jenkins.model.TransientFingerprintFacetFactory;
......@@ -995,8 +997,12 @@ public class Fingerprint implements ModelObject, Saveable {
}
}
if (modified)
if (modified) {
if (logger.isLoggable(Level.FINE)) {
logger.log(Level.FINE, "Saving trimmed {0}", getFingerprintFile(md5sum));
}
save();
}
return modified;
}
......@@ -1101,8 +1107,9 @@ public class Fingerprint implements ModelObject, Saveable {
if (facets.isEmpty()) {
file.getParentFile().mkdirs();
// JENKINS-16301: fast path for the common case.
PrintWriter w = new PrintWriter(file, "UTF-8");
AtomicFileWriter afw = new AtomicFileWriter(file);
try {
PrintWriter w = new PrintWriter(afw);
w.println("<?xml version='1.0' encoding='UTF-8'?>");
w.println("<fingerprint>");
w.print(" <timestamp>");
......@@ -1139,8 +1146,9 @@ public class Fingerprint implements ModelObject, Saveable {
w.println(" <facets/>");
w.print("</fingerprint>");
w.flush();
afw.commit();
} finally {
w.close();
afw.abort();
}
} else {
// Slower fallback that can persist facets.
......@@ -1230,7 +1238,7 @@ public class Fingerprint implements ModelObject, Saveable {
file.delete();
return null;
}
String parseError = messageOfXmlPullParserException(e);
String parseError = messageOfParseException(e);
if (parseError != null) {
logger.log(Level.WARNING, "Malformed XML in {0}: {1}", new Object[] {configFile, parseError});
file.delete();
......@@ -1240,13 +1248,13 @@ public class Fingerprint implements ModelObject, Saveable {
throw e;
}
}
private static String messageOfXmlPullParserException(Throwable t) {
if (t instanceof XmlPullParserException) {
private static String messageOfParseException(Throwable t) {
if (t instanceof XmlPullParserException || t instanceof EOFException) {
return t.getMessage();
}
Throwable t2 = t.getCause();
if (t2 != null) {
return messageOfXmlPullParserException(t2);
return messageOfParseException(t2);
} else {
return null;
}
......
......@@ -101,11 +101,13 @@ public final class FingerprintCleanupThread extends AsyncPeriodicWork {
try {
Fingerprint fp = Fingerprint.load(fingerprintFile);
if (fp == null || !fp.isAlive()) {
logger.fine("deleting obsolete " + fingerprintFile);
fingerprintFile.delete();
return true;
} else {
// get the fingerprint in the official map so have the changes visible to Jenkins
// otherwise the mutation made in FingerprintMap can override our trimming.
logger.finer("possibly trimming " + fingerprintFile);
fp = Jenkins.getInstance()._getFingerprint(fp.getHashString());
return fp.trim();
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册