Java tutorial
/******************************************************************************* * Copyright (c) 2011, 2013 AGETO Service GmbH and others. * All rights reserved. * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v1.0 which accompanies this distribution, * and is available at http://www.eclipse.org/legal/epl-v10.html. * * Contributors: * Gunnar Wagenknecht, Mike Tschierschke - initial API and implementation *******************************************************************************/ package org.eclipse.gyrex.jobs.internal.storage; import java.util.concurrent.TimeUnit; import org.eclipse.gyrex.cloud.services.locking.IExclusiveLock; import org.eclipse.gyrex.jobs.JobState; import org.eclipse.gyrex.jobs.internal.JobsActivator; import org.eclipse.gyrex.jobs.internal.JobsDebug; import org.eclipse.gyrex.jobs.internal.manager.JobHungDetectionHelper; import org.eclipse.gyrex.jobs.internal.manager.JobImpl; import org.eclipse.gyrex.jobs.internal.manager.JobManagerImpl; import org.eclipse.gyrex.jobs.internal.util.ContextHashUtil; import org.eclipse.gyrex.server.settings.SystemSetting; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Status; import org.eclipse.core.runtime.jobs.Job; import org.eclipse.core.runtime.preferences.IEclipsePreferences; import org.osgi.service.prefs.Preferences; import org.apache.commons.lang.exception.ExceptionUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * Clean-up of old job entries */ public final class CloudPreferencesCleanupJob extends Job { private static final Logger LOG = LoggerFactory.getLogger(CloudPreferencesCleanupJob.class); private long maxAge; public CloudPreferencesCleanupJob() { super("Gyrex Job Cloud Garbage Collector"); setSystem(true); setPriority(LONG); // initialize max age // (backwards compatibility; must be done in job) setMaxDaysSinceLastRun(SystemSetting .newIntegerSetting("gyrex.jobs.cleanup.maxDaysSinceLastRun", "Maximum number of days of job history that should be kept.") .usingDefault(14).create().get()); } @Override protected IStatus run(final IProgressMonitor monitor) { final IEclipsePreferences jobsNode = CloudPreferncesJobStorage.getJobsNode(); final IEclipsePreferences jobsHistoryNode = CloudPreferncesJobHistoryStorage.getJobsHistoryNode(); try { // ensure the preference tree is current (bug 360402) LOG.info("Refreshing job definitions..."); jobsNode.sync(); LOG.info("Cleaning up old job definitions older than {} days...", TimeUnit.MILLISECONDS.toDays(maxAge)); final long now = System.currentTimeMillis(); final String[] childrenNames = jobsNode.childrenNames(); for (final String internalId : childrenNames) { final String externalId = ContextHashUtil.getExternalId(internalId); JobImpl job = CloudPreferncesJobStorage.readJob(externalId, jobsNode.node(internalId)); // acquire lock (see bug 363423) final IExclusiveLock lock = JobManagerImpl.acquireLock(job); try { // re-read job in lock job = CloudPreferncesJobStorage.readJob(externalId, jobsNode.node(internalId)); // fix hung jobs if (JobHungDetectionHelper.isStuck(internalId, job, true)) { LOG.info( "Resetting job {} stuck in state {} (queued {} minutes and started {} minutes ago).", new Object[] { job.getId(), job.getState(), TimeUnit.MILLISECONDS .toMinutes(System.currentTimeMillis() - job.getLastQueued()), TimeUnit.MILLISECONDS .toMinutes(System.currentTimeMillis() - job.getLastStart()) }); // set inactive final Preferences jobNode = jobsNode.node(internalId); jobNode.put(CloudPreferncesJobStorage.PROPERTY_STATUS, JobState.NONE.name()); jobNode.remove(CloudPreferncesJobStorage.PROPERTY_ACTIVE); jobNode.flush(); job = CloudPreferncesJobStorage.readJob(externalId, jobsNode.node(internalId)); } // remove only jobs in state NONE if (job.getState() != JobState.NONE) { if (JobsDebug.cleanup) { LOG.debug("Skipping active job {}...", job.getId()); } continue; } // remove only jobs not older then maxAge final long jobAge = now - Math.max(job.getLastResultTimestamp(), Math.max(job.getLastQueued(), job.getLastStart())); if (jobAge < maxAge) { if (JobsDebug.cleanup) { LOG.debug("Skipping too young job {} (age {} days)...", job.getId(), TimeUnit.MILLISECONDS.toDays(jobAge)); } continue; } LOG.info("Removing job {}.", externalId); if (jobsHistoryNode.nodeExists(internalId)) { jobsHistoryNode.node(internalId).removeNode(); jobsHistoryNode.flush(); } if (jobsNode.nodeExists(internalId)) { jobsNode.node(internalId).removeNode(); jobsNode.flush(); } } finally { lock.release(); } } LOG.info("Finished clean-up of old job definitions."); } catch (final Exception e) { LOG.warn("Unable to clean-up old job definitions. {}", ExceptionUtils.getRootCauseMessage(e)); return new Status(IStatus.ERROR, JobsActivator.SYMBOLIC_NAME, String.format( "Unable to clean-up old job definitions. %s", ExceptionUtils.getRootCauseMessage(e)), e); } return Status.OK_STATUS; } public void setMaxDaysSinceLastRun(final int maxDaysSinceLastRun) { if (maxDaysSinceLastRun > 0) { maxAge = TimeUnit.DAYS.toMillis(maxDaysSinceLastRun); } else { maxAge = Long.MAX_VALUE; } } }