/hudson-core/src/main/java/hudson/tasks/LogRotator.java
http://github.com/hudson/hudson · Java · 341 lines · 204 code · 40 blank · 97 comment · 57 complexity · 775060514cf901dc8560b526223fad4a MD5 · raw file
- /*
- * The MIT License
- *
- * Copyright (c) 2004-2011, Oracle Corporation, Kohsuke Kawaguchi, Martin Eigenbrodt,
- * Anton Kozak, Nikita Levyankov
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
- package hudson.tasks;
- import hudson.model.Describable;
- import hudson.model.Descriptor;
- import hudson.model.Job;
- import hudson.model.Run;
- import hudson.scm.SCM;
- import java.io.IOException;
- import java.util.Calendar;
- import java.util.GregorianCalendar;
- import java.util.List;
- import java.util.logging.Logger;
- import org.kohsuke.stapler.DataBoundConstructor;
- import static java.util.logging.Level.FINE;
- import static java.util.logging.Level.FINER;
- /**
- * Deletes old log files.
- *
- * TODO: is there any other task that follows the same pattern?
- * try to generalize this just like {@link SCM} or {@link BuildStep}.
- *
- * @author Kohsuke Kawaguchi
- */
- public class LogRotator implements Describable<LogRotator> {
- private static final Logger LOGGER = Logger.getLogger(LogRotator.class.getName());
- /**
- * If not -1, history is only kept up to this days.
- */
- private final int daysToKeep;
- /**
- * If not -1, only this number of build logs are kept.
- */
- private final int numToKeep;
- /**
- * If not -1 nor null, artifacts are only kept up to this days.
- * Null handling is necessary to remain data compatible with old versions.
- * @since 1.350
- */
- private final Integer artifactDaysToKeep;
- /**
- * If not -1 nor null, only this number of builds have their artifacts kept.
- * Null handling is necessary to remain data compatible with old versions.
- * @since 1.350
- */
- private final Integer artifactNumToKeep;
- @DataBoundConstructor
- public LogRotator (String logrotate_days, String logrotate_nums, String logrotate_artifact_days, String logrotate_artifact_nums) {
- this (parse(logrotate_days),parse(logrotate_nums),
- parse(logrotate_artifact_days),parse(logrotate_artifact_nums));
- }
- public static int parse(String p) {
- if(p==null) return -1;
- try {
- return Integer.parseInt(p);
- } catch (NumberFormatException e) {
- return -1;
- }
- }
- /**
- * @deprecated since 1.350.
- * Use {@link #LogRotator(int, int, int, int)}
- */
- public LogRotator(int daysToKeep, int numToKeep) {
- this(daysToKeep, numToKeep, -1, -1);
- }
- public LogRotator(int daysToKeep, int numToKeep, int artifactDaysToKeep, int artifactNumToKeep) {
- this.daysToKeep = daysToKeep;
- this.numToKeep = numToKeep;
- this.artifactDaysToKeep = artifactDaysToKeep;
- this.artifactNumToKeep = artifactNumToKeep;
- }
- public void perform(Job<?, ?> job) throws IOException, InterruptedException {
- LOGGER.log(FINE, "Running the log rotation for " + job.getFullDisplayName());
- // keep the last successful build regardless of the status
- Run lsb = job.getLastSuccessfulBuild();
- Run lstb = job.getLastStableBuild();
- List<? extends Run<?, ?>> builds = job.getBuilds();
- Calendar cal = null;
- //Delete builds
- if (-1 != numToKeep || -1 != daysToKeep) {
- if (-1 != daysToKeep) {
- cal = new GregorianCalendar();
- cal.add(Calendar.DAY_OF_YEAR, -daysToKeep);
- }
- if (-1 != numToKeep) {
- builds = builds.subList(Math.min(builds.size(), numToKeep), builds.size());
- }
- //Delete builds based on configured values. See http://issues.hudson-ci.org/browse/HUDSON-3650
- deleteBuilds(builds, lsb, lstb, cal);
- }
- cal = null;
- builds = job.getBuilds();
- //Delete build artifacts
- if (-1 != artifactNumToKeep || -1 != artifactDaysToKeep) {
- if (-1 != artifactDaysToKeep) {
- cal = new GregorianCalendar();
- cal.add(Calendar.DAY_OF_YEAR, -artifactDaysToKeep);
- }
- if (-1 != artifactNumToKeep) {
- builds = builds.subList(Math.min(builds.size(), artifactNumToKeep), builds.size());
- }
- //Delete build artifacts based on configured values. See http://issues.hudson-ci.org/browse/HUDSON-3650
- deleteBuildArtifacts(builds, lsb, lstb, cal);
- }
- }
- /**
- * Performs builds deletion
- *
- * @param builds list of builds
- * @param lastSuccessBuild last success build
- * @param lastStableBuild last stable build
- * @param cal calendar if configured
- * @throws IOException if configured
- */
- private void deleteBuilds(List<? extends Run<?, ?>> builds, Run lastSuccessBuild, Run lastStableBuild, Calendar cal)
- throws IOException {
- for (Run currentBuild : builds) {
- if (allowDeleteBuild(lastSuccessBuild, lastStableBuild, currentBuild, cal)) {
- LOGGER.log(FINER, currentBuild.getFullDisplayName() + " is to be removed");
- currentBuild.delete();
- }
- }
- }
- /**
- * Checks whether current build could be deleted.
- * If current build equals to last Success Build or last Stable Build or currentBuild is configured to keep logs or
- * currentBuild timestamp is before configured calendar value - return false, otherwise return true.
- *
- * @param lastSuccessBuild {@link Run}
- * @param lastStableBuild {@link Run}
- * @param currentBuild {@link Run}
- * @param cal {@link Calendar}
- * @return true - if deletion is allowed, false - otherwise.
- */
- private boolean allowDeleteBuild(Run lastSuccessBuild, Run lastStableBuild, Run currentBuild, Calendar cal) {
- if (currentBuild.isKeepLog()) {
- LOGGER.log(FINER, currentBuild.getFullDisplayName() + " is not GC-ed because it's marked as a keeper");
- return false;
- }
- if (currentBuild == lastSuccessBuild) {
- LOGGER.log(FINER,
- currentBuild.getFullDisplayName() + " is not GC-ed because it's the last successful build");
- return false;
- }
- if (currentBuild == lastStableBuild) {
- LOGGER.log(FINER, currentBuild.getFullDisplayName() + " is not GC-ed because it's the last stable build");
- return false;
- }
- if (null != cal && !currentBuild.getTimestamp().before(cal)) {
- LOGGER.log(FINER, currentBuild.getFullDisplayName() + " is not GC-ed because it's still new");
- return false;
- }
- return true;
- }
- /**
- * Performs build artifacts deletion
- *
- * @param builds list of builds
- * @param lastSuccessBuild last success build
- * @param lastStableBuild last stable build
- * @param cal calendar if configured
- * @throws IOException if configured
- */
- private void deleteBuildArtifacts(List<? extends Run<?, ?>> builds, Run lastSuccessBuild, Run lastStableBuild,
- Calendar cal) throws IOException {
- for (Run currentBuild : builds) {
- if (allowDeleteArtifact(lastSuccessBuild, lastStableBuild, currentBuild, cal)) {
- currentBuild.deleteArtifacts();
- }
- }
- }
- /**
- * Checks whether artifacts from build could be deleted.
- * If current build equals to last Success Build or last Stable Build or currentBuild is configured to keep logs or
- * currentBuild timestamp is before configured calendar value - return false, otherwise return true.
- *
- * @param lastSuccessBuild {@link Run}
- * @param lastStableBuild {@link Run}
- * @param currentBuild {@link Run}
- * @param cal {@link Calendar}
- * @return true - if deletion is allowed, false - otherwise.
- */
- private boolean allowDeleteArtifact(Run lastSuccessBuild, Run lastStableBuild, Run currentBuild, Calendar cal) {
- if (currentBuild.isKeepLog()) {
- LOGGER.log(FINER,
- currentBuild.getFullDisplayName() + " is not purged of artifacts because it's marked as a keeper");
- return false;
- }
- if (currentBuild == lastSuccessBuild) {
- LOGGER.log(FINER, currentBuild.getFullDisplayName()
- + " is not purged of artifacts because it's the last successful build");
- return false;
- }
- if (currentBuild == lastStableBuild) {
- LOGGER.log(FINER,
- currentBuild.getFullDisplayName() + " is not purged of artifacts because it's the last stable build");
- return false;
- }
- if (null != cal && !currentBuild.getTimestamp().before(cal)) {
- LOGGER.log(FINER, currentBuild.getFullDisplayName() + " is not purged of artifacts because it's still new");
- return false;
- }
- return true;
- }
- public int getDaysToKeep() {
- return daysToKeep;
- }
- public int getNumToKeep() {
- return numToKeep;
- }
- public int getArtifactDaysToKeep() {
- return unbox(artifactDaysToKeep);
- }
- public int getArtifactNumToKeep() {
- return unbox(artifactNumToKeep);
- }
- public String getDaysToKeepStr() {
- return toString(daysToKeep);
- }
- public String getNumToKeepStr() {
- return toString(numToKeep);
- }
- public String getArtifactDaysToKeepStr() {
- return toString(artifactDaysToKeep);
- }
- public String getArtifactNumToKeepStr() {
- return toString(artifactNumToKeep);
- }
- private int unbox(Integer i) {
- return i==null ? -1: i;
- }
- private String toString(Integer i) {
- if (i==null || i==-1) return "";
- return String.valueOf(i);
- }
- public LRDescriptor getDescriptor() {
- return DESCRIPTOR;
- }
- public static final LRDescriptor DESCRIPTOR = new LRDescriptor();
- public static final class LRDescriptor extends Descriptor<LogRotator> {
- public String getDisplayName() {
- return "Log Rotation";
- }
- }
- @Override
- public boolean equals(Object o) {
- if (this == o) {
- return true;
- }
- if (o == null || getClass() != o.getClass()) {
- return false;
- }
- LogRotator that = (LogRotator) o;
- if (daysToKeep != that.daysToKeep) {
- return false;
- }
- if (numToKeep != that.numToKeep) {
- return false;
- }
- if (artifactDaysToKeep != null ? !artifactDaysToKeep.equals(that.artifactDaysToKeep)
- : that.artifactDaysToKeep != null) {
- return false;
- }
- if (artifactNumToKeep != null ? !artifactNumToKeep.equals(that.artifactNumToKeep)
- : that.artifactNumToKeep != null) {
- return false;
- }
- return true;
- }
- @Override
- public int hashCode() {
- int result = daysToKeep;
- result = 31 * result + numToKeep;
- result = 31 * result + (artifactDaysToKeep != null ? artifactDaysToKeep.hashCode() : 0);
- result = 31 * result + (artifactNumToKeep != null ? artifactNumToKeep.hashCode() : 0);
- return result;
- }
- }