Author: cziegeler
Date: Wed Feb 19 13:30:58 2014
New Revision: 1569737
URL: http://svn.apache.org/r1569737
Log:
SLING-3392 : JobManager MaintenanceTask should not rely on search for removing
locks
Modified:
sling/trunk/bundles/extensions/event/src/main/java/org/apache/sling/event/impl/jobs/JobManagerImpl.java
sling/trunk/bundles/extensions/event/src/main/java/org/apache/sling/event/impl/jobs/MaintenanceTask.java
Modified:
sling/trunk/bundles/extensions/event/src/main/java/org/apache/sling/event/impl/jobs/JobManagerImpl.java
URL:
http://svn.apache.org/viewvc/sling/trunk/bundles/extensions/event/src/main/java/org/apache/sling/event/impl/jobs/JobManagerImpl.java?rev=1569737&r1=1569736&r2=1569737&view=diff
==============================================================================
---
sling/trunk/bundles/extensions/event/src/main/java/org/apache/sling/event/impl/jobs/JobManagerImpl.java
(original)
+++
sling/trunk/bundles/extensions/event/src/main/java/org/apache/sling/event/impl/jobs/JobManagerImpl.java
Wed Feb 19 13:30:58 2014
@@ -1202,7 +1202,7 @@ public class JobManagerImpl
/**
* Try to get a "lock" for a resource
*/
- private boolean lock(final String id) {
+ private boolean lock(final String jobTopic, final String id) {
if ( logger.isDebugEnabled() ) {
logger.debug("Trying to get lock for {}", id);
}
@@ -1213,6 +1213,8 @@ public class JobManagerImpl
final String lockName = ResourceHelper.filterName(id);
final StringBuilder sb = new
StringBuilder(this.configuration.getLocksPath());
sb.append('/');
+ sb.append(jobTopic.replace('/', '.'));
+ sb.append('/');
sb.append(lockName);
final String path = sb.toString();
@@ -1282,7 +1284,7 @@ public class JobManagerImpl
Utility.sendNotification(this.eventAdmin,
NotificationConstants.TOPIC_JOB_CANCELLED, jobTopic, jobName, jobProperties,
null);
} else {
// check for unique jobs
- if ( jobName != null && !this.lock(jobName) ) {
+ if ( jobName != null && !this.lock(jobTopic, jobName) ) {
logger.debug("Discarding duplicate job {}",
Utility.toString(jobTopic, jobName, jobProperties));
return null;
} else {
Modified:
sling/trunk/bundles/extensions/event/src/main/java/org/apache/sling/event/impl/jobs/MaintenanceTask.java
URL:
http://svn.apache.org/viewvc/sling/trunk/bundles/extensions/event/src/main/java/org/apache/sling/event/impl/jobs/MaintenanceTask.java?rev=1569737&r1=1569736&r2=1569737&view=diff
==============================================================================
---
sling/trunk/bundles/extensions/event/src/main/java/org/apache/sling/event/impl/jobs/MaintenanceTask.java
(original)
+++
sling/trunk/bundles/extensions/event/src/main/java/org/apache/sling/event/impl/jobs/MaintenanceTask.java
Wed Feb 19 13:30:58 2014
@@ -20,24 +20,24 @@ package org.apache.sling.event.impl.jobs
import java.io.IOException;
import java.io.ObjectInputStream;
+import java.util.ArrayList;
import java.util.Calendar;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
-import org.apache.jackrabbit.util.ISO8601;
-import org.apache.jackrabbit.util.ISO9075;
import org.apache.sling.api.resource.LoginException;
import org.apache.sling.api.resource.PersistenceException;
-import org.apache.sling.api.resource.QuerySyntaxException;
import org.apache.sling.api.resource.Resource;
import org.apache.sling.api.resource.ResourceResolver;
import org.apache.sling.api.resource.ResourceResolverFactory;
+import org.apache.sling.api.resource.ResourceUtil;
import org.apache.sling.api.resource.ValueMap;
import org.apache.sling.discovery.InstanceDescription;
import org.apache.sling.event.impl.jobs.config.QueueConfigurationManager;
import
org.apache.sling.event.impl.jobs.config.QueueConfigurationManager.QueueInfo;
+import org.apache.sling.event.impl.support.BatchResourceRemover;
import org.apache.sling.event.impl.support.Environment;
import org.apache.sling.event.impl.support.ResourceHelper;
import org.apache.sling.event.jobs.Job;
@@ -343,25 +343,54 @@ public class MaintenanceTask {
}
}
- // lock cleanup is done every 3 minutes
- if ( cleanUpCounter % 3 == 0 ) {
- this.lockCleanup(topologyCapabilities);
- }
+ // lock cleanup is done every minute
+ this.lockCleanup(topologyCapabilities);
}
/**
* Clean up the locks
- * All locks older than three minutes are removed
+ * All locks older than two minutes are removed
*/
private void lockCleanup(final TopologyCapabilities caps) {
if ( caps != null && caps.isLeader() ) {
this.logger.debug("Cleaning up job resource tree: removing
obsolete locks");
+ final List<Resource> candidates = new ArrayList<Resource>();
ResourceResolver resolver = null;
try {
resolver =
this.resourceResolverFactory.getAdministrativeResourceResolver(null);
+ final Resource parentResource =
resolver.getResource(this.configuration.getLocksPath());
final Calendar startDate = Calendar.getInstance();
- startDate.add(Calendar.MINUTE, -3);
+ startDate.add(Calendar.MINUTE, -2);
+
+ this.lockCleanup(caps, candidates, parentResource, startDate);
+ final BatchResourceRemover remover = new
BatchResourceRemover();
+ boolean batchRemove = true;
+ for(final Resource lockResource : candidates) {
+ if ( caps.isActive() ) {
+ try {
+ if ( batchRemove ) {
+ remover.delete(lockResource);
+ } else {
+ resolver.delete(lockResource);
+ resolver.commit();
+ }
+ } catch ( final PersistenceException pe) {
+ batchRemove = false;
+ this.ignoreException(pe);
+ resolver.refresh();
+ }
+ } else {
+ break;
+ }
+ }
+ try {
+ resolver.commit();
+ } catch ( final PersistenceException pe) {
+ this.ignoreException(pe);
+ resolver.refresh();
+ }
+/* Old implementation using a query
final StringBuilder buf = new StringBuilder(64);
buf.append("//element(*)[@");
@@ -390,6 +419,7 @@ public class MaintenanceTask {
}
} catch (final QuerySyntaxException qse) {
this.ignoreException(qse);
+*/
} catch (final LoginException le) {
this.ignoreException(le);
} finally {
@@ -401,6 +431,31 @@ public class MaintenanceTask {
}
/**
+ * Recursive lock cleanup
+ */
+ private void lockCleanup(final TopologyCapabilities caps,
+ final List<Resource> candidates,
+ final Resource parentResource,
+ final Calendar startDate) {
+ for(final Resource childResource : parentResource.getChildren()) {
+ if ( caps.isActive() ) {
+ final ValueMap vm = ResourceUtil.getValueMap(childResource);
+ final Calendar created = vm.get(Utility.PROPERTY_LOCK_CREATED,
Calendar.class);
+ if ( created != null ) {
+ // lock resource
+ if ( created.before(startDate) ) {
+ candidates.add(childResource);
+ }
+ } else {
+ lockCleanup(caps, candidates, childResource, startDate);
+ }
+ } else {
+ break;
+ }
+ }
+ }
+
+ /**
* Simple empty folder removes empty folders for the last five minutes
* from an hour ago!
* If folder for minute 59 is removed, we check the hour folder as well.