Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBob Foster2015-03-19 13:24:55 -0400
committerBob Foster2015-03-19 13:27:12 -0400
commit1007564ea806c3e608e1183019530b9c2b53b204 (patch)
tree8767a2701c8babb49f99e89eba69b98e6856578b
parent1c6c9966ea9f26c6571e9f10604eb7fb22b82127 (diff)
downloadorg.eclipse.hudson.core-diskusage.tar.gz
org.eclipse.hudson.core-diskusage.tar.xz
org.eclipse.hudson.core-diskusage.zip
Add disk usage api to build and jobdiskusage
-rw-r--r--hudson-core/src/main/java/hudson/Util.java100
-rw-r--r--hudson-core/src/main/java/hudson/matrix/MatrixConfiguration.java38
-rw-r--r--hudson-core/src/main/java/hudson/model/AbstractModelObject.java11
-rw-r--r--hudson-core/src/main/java/hudson/model/AbstractProject.java12
-rw-r--r--hudson-core/src/main/java/hudson/model/BuildHistory.java2
-rw-r--r--hudson-core/src/main/java/hudson/model/Hudson.java20
-rw-r--r--hudson-core/src/main/java/hudson/model/Job.java71
-rw-r--r--hudson-core/src/main/java/hudson/model/Run.java12
-rw-r--r--hudson-core/src/main/java/hudson/model/RunMap.java15
9 files changed, 242 insertions, 39 deletions
diff --git a/hudson-core/src/main/java/hudson/Util.java b/hudson-core/src/main/java/hudson/Util.java
index 5bf7ac91..19da262e 100644
--- a/hudson-core/src/main/java/hudson/Util.java
+++ b/hudson-core/src/main/java/hudson/Util.java
@@ -15,50 +15,40 @@
*******************************************************************************/
package hudson;
-import hudson.model.TaskListener;
+import hudson.Proc.LocalProc;
+import hudson.matrix.MatrixProject;
+import hudson.model.FreeStyleProject;
import hudson.model.Hudson;
-
+import hudson.model.Job;
+import hudson.model.TaskListener;
+import hudson.model.TopLevelItem;
import hudson.util.IOException2;
import hudson.util.QuotedStringTokenizer;
import hudson.util.VariableResolver;
-import hudson.Proc.LocalProc;
-import org.eclipse.hudson.jna.NativeAccessException;
-
-import org.eclipse.hudson.jna.NativeUtils;
-import org.apache.tools.ant.BuildException;
-import org.apache.tools.ant.Project;
-import org.apache.tools.ant.types.FileSet;
-import org.apache.tools.ant.taskdefs.Chmod;
-import org.apache.tools.ant.taskdefs.Copy;
-import org.apache.commons.lang3.time.FastDateFormat;
-import org.apache.commons.io.IOUtils;
-
-import javax.crypto.SecretKey;
-import javax.crypto.spec.SecretKeySpec;
-
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
+import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
+import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
+import java.io.PrintStream;
import java.io.Reader;
import java.io.StringReader;
-import java.io.Writer;
-import java.io.PrintStream;
-import java.io.InputStreamReader;
-import java.io.FileInputStream;
import java.io.UnsupportedEncodingException;
+import java.io.Writer;
import java.net.InetAddress;
-import java.net.UnknownHostException;
import java.net.URI;
import java.net.URISyntaxException;
+import java.net.UnknownHostException;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.charset.CharacterCodingException;
+import java.nio.charset.Charset;
import java.nio.charset.CharsetEncoder;
import java.security.DigestInputStream;
import java.security.MessageDigest;
@@ -66,23 +56,33 @@ import java.security.NoSuchAlgorithmException;
import java.text.NumberFormat;
import java.text.ParseException;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Collection;
+import java.util.Collections;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.MissingResourceException;
import java.util.Properties;
import java.util.ResourceBundle;
+import java.util.Set;
import java.util.SimpleTimeZone;
import java.util.StringTokenizer;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
-import java.nio.charset.Charset;
+import javax.crypto.SecretKey;
+import javax.crypto.spec.SecretKeySpec;
+import org.apache.commons.io.IOUtils;
+import org.apache.commons.lang3.time.FastDateFormat;
+import org.apache.tools.ant.BuildException;
+import org.apache.tools.ant.Project;
+import org.apache.tools.ant.taskdefs.Chmod;
+import org.apache.tools.ant.taskdefs.Copy;
+import org.apache.tools.ant.types.FileSet;
+import org.eclipse.hudson.jna.NativeAccessException;
+import org.eclipse.hudson.jna.NativeUtils;
/**
* Various utility methods that don't have more proper home.
@@ -1205,6 +1205,54 @@ public class Util {
return null;
}
+
+ private static long calculateDiskUsage(File dir, long usage) {
+ File[] children = dir.listFiles();
+ for (File child : children) {
+ if (child.isDirectory()) {
+ usage += calculateDiskUsage(child, usage);
+ } else {
+ usage += child.length();
+ }
+ }
+ return usage;
+ }
+
+ /**
+ * Return the sum of the lengths of the files recursively in directory.
+ *
+ * @param dir directory path
+ * @return total disk usage
+ */
+ public static long calculateDiskUsage(File dir) {
+ if (dir.exists() && dir.isDirectory()) {
+ return calculateDiskUsage(dir, 0);
+ }
+ return 0;
+ }
+
+ public static long calculateWorkspaceDiskUsage(Job job) {
+ File workspace = null;
+ try {
+ String customWorkspace = job instanceof FreeStyleProject ? ((FreeStyleProject)job).getCustomWorkspace() :
+ (job instanceof MatrixProject ? ((MatrixProject)job).getCustomWorkspace() : null);
+ if (customWorkspace != null) {
+ EnvVars vars = new EnvVars(EnvVars.masterEnvVars);
+ FilePath ws = Hudson.getInstance().getRootPath().child(vars.expand(customWorkspace));
+ workspace = new File(ws.getRemote());
+ }
+
+ } catch (IOException e) {
+ }
+ if (workspace == null && job instanceof TopLevelItem) {
+ TopLevelItem item = (TopLevelItem) job;
+ workspace = Hudson.getInstance().getWorkspaceDir(item);
+ }
+ if (workspace != null && workspace.exists() && workspace.isDirectory()) {
+ return calculateDiskUsage(workspace);
+ }
+ return 0;
+ }
/**
* Encodes the URL by RFC 2396.
diff --git a/hudson-core/src/main/java/hudson/matrix/MatrixConfiguration.java b/hudson-core/src/main/java/hudson/matrix/MatrixConfiguration.java
index 4b1b35aa..0e0ffff0 100644
--- a/hudson-core/src/main/java/hudson/matrix/MatrixConfiguration.java
+++ b/hudson-core/src/main/java/hudson/matrix/MatrixConfiguration.java
@@ -16,11 +16,12 @@
package hudson.matrix;
+import hudson.EnvVars;
+import hudson.FilePath;
import hudson.Util;
-import hudson.security.ACL;
-import hudson.util.DescribableList;
import hudson.model.AbstractBuild;
import hudson.model.Cause;
+import hudson.model.Cause.LegacyCodeCause;
import hudson.model.CauseAction;
import hudson.model.DependencyGraph;
import hudson.model.Descriptor;
@@ -31,15 +32,16 @@ import hudson.model.JDK;
import hudson.model.Label;
import hudson.model.ParametersAction;
import hudson.model.Project;
-import hudson.model.SCMedItem;
import hudson.model.Queue.NonBlockingTask;
-import hudson.model.Cause.LegacyCodeCause;
+import hudson.model.SCMedItem;
import hudson.scm.SCM;
+import hudson.security.ACL;
import hudson.tasks.BuildWrapper;
import hudson.tasks.Builder;
import hudson.tasks.LogRotator;
import hudson.tasks.Publisher;
-
+import hudson.util.DescribableList;
+import java.io.File;
import java.io.IOException;
import java.util.List;
import java.util.Map;
@@ -80,6 +82,32 @@ public class MatrixConfiguration extends Project<MatrixConfiguration, MatrixRun>
this.digestName = c.digest().substring(0, 8);
}
+ @Override
+ protected long calculateWorkspaceDiskUsage() {
+ // like MatrixRun.RunnerImpl.decideWorkspace, for master only
+ File workspace = Hudson.getInstance().getWorkspaceDir(getParent());
+ String customWorkspace = getParent().getCustomWorkspace();
+ if (customWorkspace != null) {
+ EnvVars vars = new EnvVars(EnvVars.masterEnvVars);
+ FilePath ws = Hudson.getInstance().getRootPath().child(vars.expand(customWorkspace));
+ workspace = new File(ws.getRemote());
+ }
+
+ if (useShortWorkspaceName) {
+ workspace = new File(workspace, getDigestName());
+ } else {
+ String combinationPath = combination.toString('/', '/');
+ String[] dirs = combinationPath.split("/");
+ for (String dir : dirs) {
+ workspace = new File(workspace, dir);
+ }
+ }
+ if (workspace.exists() && workspace.isDirectory()) {
+ return Util.calculateDiskUsage(workspace);
+ }
+ return 0;
+ }
+
/**
* Build numbers are always synchronized with the parent.
*
diff --git a/hudson-core/src/main/java/hudson/model/AbstractModelObject.java b/hudson-core/src/main/java/hudson/model/AbstractModelObject.java
index dadd8ff9..0546f4f9 100644
--- a/hudson-core/src/main/java/hudson/model/AbstractModelObject.java
+++ b/hudson-core/src/main/java/hudson/model/AbstractModelObject.java
@@ -96,8 +96,9 @@ public abstract class AbstractModelObject implements SearchableModelObject {
* @param key - the name of the configured property.
* @return the string value of the configured property, or null if there is
* no property with that key.
+ * @since 3.3.0
*/
- protected String getConfiguredHudsonProperty(String key) {
+ public static String getHudsonProperty(String key) {
if (StringUtils.isNotBlank(key)) {
String resultValue;
try {
@@ -130,6 +131,14 @@ public abstract class AbstractModelObject implements SearchableModelObject {
}
return null;
}
+
+ /**
+ * For compatibility with pre-3.3.0.
+ * @see #getHudsonProperty(java.lang.String)
+ */
+ protected String getConfiguredHudsonProperty(String key) {
+ return getHudsonProperty(key);
+ }
/**
* Default implementation that returns empty index.
diff --git a/hudson-core/src/main/java/hudson/model/AbstractProject.java b/hudson-core/src/main/java/hudson/model/AbstractProject.java
index d01c434e..98b34631 100644
--- a/hudson-core/src/main/java/hudson/model/AbstractProject.java
+++ b/hudson-core/src/main/java/hudson/model/AbstractProject.java
@@ -1215,6 +1215,18 @@ public abstract class AbstractProject<P extends AbstractProject<P, R>, R extends
public BuildHistory<P,R> getBuildHistoryData() {
return builds;
}
+
+ @Override
+ public void calculateDiskUsage() {
+ setWorkspaceDiskUsage(Util.calculateWorkspaceDiskUsage(this));
+ long buildsUsage = 0;
+ BuildHistory history = getBuildHistoryData();
+ for (BuildHistory.Record build : history) {
+ buildsUsage += build.getDiskUsage();
+ }
+
+ }
+
/**
* Determines Class&lt;R>.
diff --git a/hudson-core/src/main/java/hudson/model/BuildHistory.java b/hudson-core/src/main/java/hudson/model/BuildHistory.java
index 9a95bdb1..0d65e645 100644
--- a/hudson-core/src/main/java/hudson/model/BuildHistory.java
+++ b/hudson-core/src/main/java/hudson/model/BuildHistory.java
@@ -63,6 +63,8 @@ public interface BuildHistory<JobT extends Job<JobT, RunT>, RunT extends Run<Job
Date getTime();
long getDuration();
+
+ long getDiskUsage();
String getBuiltOnNodeName();
diff --git a/hudson-core/src/main/java/hudson/model/Hudson.java b/hudson-core/src/main/java/hudson/model/Hudson.java
index e400a9eb..291689ea 100644
--- a/hudson-core/src/main/java/hudson/model/Hudson.java
+++ b/hudson-core/src/main/java/hudson/model/Hudson.java
@@ -274,7 +274,7 @@ public final class Hudson extends Node implements ItemGroup<TopLevelItem>, Stapl
*/
private String instanceTag;
- private static transient final String HUDSON_WORKSPACES_PROPERTY_KEY = "HUDSON_WORKSPACES";
+ /* package private */ static transient final String HUDSON_WORKSPACES_PROPERTY_KEY = "HUDSON_WORKSPACES";
/**
* Workspace root dir which could be configured by setting HUDSON_WORKSPACES
* property.
@@ -2065,13 +2065,23 @@ public final class Hudson extends Node implements ItemGroup<TopLevelItem>, Stapl
* based on property value.
*/
public FilePath getWorkspaceFor(TopLevelItem item) {
+ return new FilePath(getWorkspaceDir(item));
+ }
+
+ /**
+ * Get the workspace directory on master. May not exist.
+ *
+ * @param item top level item (job)
+ * @return
+ */
+ public File getWorkspaceDir(TopLevelItem item) {
String workspaceRoot = getConfiguredWorkspaceRoot();
if (StringUtils.isNotBlank(workspaceRoot)) {
- return new FilePath(new File(workspaceRoot + "/" + item.getName(), WORKSPACE_DIRNAME));
+ return new File(workspaceRoot + "/" + item.getName(), WORKSPACE_DIRNAME);
} else {
- return new FilePath(new File(item.getRootDir(), WORKSPACE_DIRNAME));
+ return new File(item.getRootDir(), WORKSPACE_DIRNAME);
}
- }
+ }
/**
* Checks jndi,environment properties and system properties for
@@ -4209,7 +4219,7 @@ public final class Hudson extends Node implements ItemGroup<TopLevelItem>, Stapl
/**
* Switch to enable people to use a shorter workspace name.
*/
- private static final String WORKSPACE_DIRNAME = System.getProperty(Hudson.class.getName() + ".workspaceDirName", "workspace");
+ /* package privage */ static final String WORKSPACE_DIRNAME = System.getProperty(Hudson.class.getName() + ".workspaceDirName", "workspace");
/**
* Automatically try to launch a slave when Hudson is initialized or a new
* slave is created.
diff --git a/hudson-core/src/main/java/hudson/model/Job.java b/hudson-core/src/main/java/hudson/model/Job.java
index aea2a4a5..de606c39 100644
--- a/hudson-core/src/main/java/hudson/model/Job.java
+++ b/hudson-core/src/main/java/hudson/model/Job.java
@@ -21,6 +21,7 @@ import com.google.common.collect.Sets;
import hudson.Extension;
import hudson.ExtensionPoint;
import hudson.PermalinkList;
+import hudson.Util;
import hudson.cli.declarative.CLIResolver;
import hudson.model.BuildHistory.Record;
import hudson.model.Descriptor.FormException;
@@ -111,9 +112,9 @@ import org.kohsuke.stapler.export.Exported;
public abstract class Job<JobT extends Job<JobT, RunT>, RunT extends Run<JobT, RunT>>
extends AbstractItem implements ExtensionPoint, StaplerOverridable, IJob, ICascadingJob {
- private static transient final String HUDSON_BUILDS_PROPERTY_KEY = "HUDSON_BUILDS";
+ static transient final String HUDSON_BUILDS_PROPERTY_KEY = "HUDSON_BUILDS";
private static transient final String PROJECT_PROPERTY_KEY_PREFIX = "has";
- private static transient final String BUILDS_DIRNAME = "builds";
+ static transient final String BUILDS_DIRNAME = "builds";
public static final String PROPERTY_NAME_SEPARATOR = ";";
public static final String LOG_ROTATOR_PROPERTY_NAME = "logRotator";
public static final String PARAMETERS_DEFINITION_JOB_PROPERTY_PROPERTY_NAME = "parametersDefinitionProperties";
@@ -188,6 +189,19 @@ public abstract class Job<JobT extends Job<JobT, RunT>, RunT extends Run<JobT, R
* @since 2.2.0
*/
private Set<String> cascadingJobProperties = new CopyOnWriteArraySet<String>();
+ /**
+ * Disk usage of workspace directory on master.
+ *
+ * @since 3.3.0
+ */
+ private long workspaceDiskUsage;
+ /**
+ * Disk usage of build directories on master.
+ *
+ * @since 3.3.0
+ */
+ private long buildsDiskUsage;
+
/**
* Selected cascadingProject for this job.
*/
@@ -732,6 +746,59 @@ public abstract class Job<JobT extends Job<JobT, RunT>, RunT extends Run<JobT, R
public boolean supportsLogRotator() {
return true;
}
+
+ public long getWorkspaceDiskUsage() {
+ return workspaceDiskUsage;
+ }
+
+ public long getBuildsDiskUsage() {
+ return buildsDiskUsage;
+ }
+
+ protected void setWorkspaceDiskUsage(long usage) {
+ workspaceDiskUsage = usage;
+ }
+
+ protected void setBuildsDiskUsage(long usage) {
+ buildsDiskUsage = usage;
+ }
+
+ /**
+ * Calculate disk usage.
+ *
+ * @see #calculateBuildsDiskUsage()
+ * @see #calculateWorkspaceDiskUsage()
+ */
+ public void calculateDiskUsage() {
+ setWorkspaceDiskUsage(calculateWorkspaceDiskUsage());
+ setBuildsDiskUsage(calculateBuildsDiskUsage());
+
+ }
+
+ /**
+ * Calculate the disk space used for workspace on master.
+ *
+ * The default implementation works only for TopLevelItems.
+ * @return disk usage
+ */
+ protected long calculateWorkspaceDiskUsage() {
+ return Util.calculateWorkspaceDiskUsage(this);
+ }
+
+ /**
+ * Calculate the disk space used by builds on master.
+ *
+ * @return disk usage
+ */
+ protected long calculateBuildsDiskUsage() {
+ BuildHistory buildHistory = getBuildHistoryData();
+ long buildsUsage = 0;
+ List<BuildHistory.Record> records = buildHistory.allRecords();
+ for (BuildHistory.Record record : records) {
+ buildsUsage += record.getDiskUsage();
+ }
+ return buildsUsage;
+ }
/**
* Method converts JobProperties to cascading values.
diff --git a/hudson-core/src/main/java/hudson/model/Run.java b/hudson-core/src/main/java/hudson/model/Run.java
index 329a0943..7ffbfd37 100644
--- a/hudson-core/src/main/java/hudson/model/Run.java
+++ b/hudson-core/src/main/java/hudson/model/Run.java
@@ -200,6 +200,10 @@ public abstract class Run<JobT extends Job<JobT, RunT>, RunT extends Run<JobT, R
* Number of milli-seconds it took to run this build.
*/
protected long duration;
+ /**
+ * Disk usage of build in bytes.
+ */
+ protected long diskUsage;
/**
* Charset in which the log file is written. For compatibility reason, this
* field may be null. For persistence, this field is string and not
@@ -384,6 +388,7 @@ public abstract class Run<JobT extends Job<JobT, RunT>, RunT extends Run<JobT, R
this.displayName = String.format("%s [In Error]",key.referenced.displayName);
this.duration = key.referenced.duration;
+ this.diskUsage = key.referenced.diskUsage;
this.result = key.referenced.result;
this.state = key.referenced.state;
this.timestamp = key.referenced.timeInMillis;
@@ -671,6 +676,10 @@ public abstract class Run<JobT extends Job<JobT, RunT>, RunT extends Run<JobT, R
public long getDuration() {
return duration;
}
+
+ public long getDiskUsage() {
+ return diskUsage;
+ }
/**
* Gets the icon color for display.
@@ -1524,6 +1533,9 @@ public abstract class Run<JobT extends Job<JobT, RunT>, RunT extends Run<JobT, R
} finally {
long end = System.currentTimeMillis();
duration = Math.max(end - start, 0); // @see HUDSON-5844
+
+ diskUsage = Util.calculateDiskUsage(getRootDir());
+ getParent().calculateDiskUsage();
// advance the state.
// the significance of doing this is that Hudson
diff --git a/hudson-core/src/main/java/hudson/model/RunMap.java b/hudson-core/src/main/java/hudson/model/RunMap.java
index 52c17b38..f83b2b77 100644
--- a/hudson-core/src/main/java/hudson/model/RunMap.java
+++ b/hudson-core/src/main/java/hudson/model/RunMap.java
@@ -814,6 +814,7 @@ public final class RunMap<J extends Job<J, R>, R extends Run<J, R>>
long timeInMillis;
long duration;
+ long diskUsage;
String fullDisplayName;
String displayName;
String description;
@@ -863,6 +864,7 @@ public final class RunMap<J extends Job<J, R>, R extends Run<J, R>>
setDisplayName( build.getDisplayName());
setDescription( build.getDescription());
setDuration( build.getDuration());
+ setDiskUsage( build.getDiskUsage() );
if ( build instanceof AbstractBuild) {
setBuiltOnNodeName(((AbstractBuild)build).getBuiltOnStr());
@@ -908,6 +910,14 @@ public final class RunMap<J extends Job<J, R>, R extends Run<J, R>>
this.duration = duration;
markDirty(true);
}
+
+ void setDiskUsage(long diskUsage) {
+ if ( this.diskUsage == diskUsage) {
+ return;
+ }
+ this.diskUsage = diskUsage;
+ markDirty(true);
+ }
void setDisplayName(String name) {
if ( StringUtils.equals(this.displayName, name)) {
@@ -1054,6 +1064,11 @@ public final class RunMap<J extends Job<J, R>, R extends Run<J, R>>
}
@Override
+ public long getDiskUsage() {
+ return diskUsage;
+ }
+
+ @Override
public String getUrl() {
return url;
}

Back to the top