Author: cziegeler
Date: Tue Aug 31 09:50:02 2010
New Revision: 991134
URL: http://svn.apache.org/viewvc?rev=991134&view=rev
Log:
SLING-1687 : JobStatusProvider should lazy load events when returning
Added:
sling/trunk/bundles/extensions/event/src/main/java/org/apache/sling/event/JobsIterator.java
(with props)
sling/trunk/bundles/extensions/event/src/main/java/org/apache/sling/event/impl/job/JobsIteratorImpl.java
(with props)
Modified:
sling/trunk/bundles/extensions/event/src/main/java/org/apache/sling/event/JobStatusProvider.java
sling/trunk/bundles/extensions/event/src/main/java/org/apache/sling/event/impl/AbstractRepositoryEventHandler.java
sling/trunk/bundles/extensions/event/src/main/java/org/apache/sling/event/impl/EventHelper.java
sling/trunk/bundles/extensions/event/src/main/java/org/apache/sling/event/impl/JobEventHandler.java
Modified:
sling/trunk/bundles/extensions/event/src/main/java/org/apache/sling/event/JobStatusProvider.java
URL:
http://svn.apache.org/viewvc/sling/trunk/bundles/extensions/event/src/main/java/org/apache/sling/event/JobStatusProvider.java?rev=991134&r1=991133&r2=991134&view=diff
==============================================================================
---
sling/trunk/bundles/extensions/event/src/main/java/org/apache/sling/event/JobStatusProvider.java
(original)
+++
sling/trunk/bundles/extensions/event/src/main/java/org/apache/sling/event/JobStatusProvider.java
Tue Aug 31 09:50:02 2010
@@ -37,7 +37,9 @@ public interface JobStatusProvider {
* Return a list of currently scheduled jobs.
* @param topic Topic can be used as a filter, if it is non-null, only
jobs with this topic will be returned.
* @return A non null collection.
+ * @deprecated Use {...@link #queryScheduledJobs(String, Map...)} instead.
*/
+ @Deprecated
Collection<Event> getScheduledJobs(String topic);
/**
@@ -45,7 +47,9 @@ public interface JobStatusProvider {
* in the cluster, there could be more than one job in processing
* @param topic Topic can be used as a filter, if it is non-null, only
jobs with this topic will be returned.
* @return A non null collection.
+ * @deprecated Use {...@link #queryCurrentJobs(String, Map...)} instead.
*/
+ @Deprecated
Collection<Event> getCurrentJobs(String topic);
/**
@@ -55,7 +59,9 @@ public interface JobStatusProvider {
* must match the template (AND query). By providing
several maps, different filters
* are possible (OR query).
* @return A non null collection.
+ * @deprecated Use {...@link #queryScheduledJobs(String, Map...)} instead.
*/
+ @Deprecated
Collection<Event> getScheduledJobs(String topic, Map<String, Object>...
filterProps);
/**
@@ -66,7 +72,9 @@ public interface JobStatusProvider {
* must match the template (AND query). By providing
several maps, different filters
* are possible (OR query).
* @return A non null collection.
+ * @deprecated Use {...@link #queryCurrentJobs(String, Map...)} instead.
*/
+ @Deprecated
Collection<Event> getCurrentJobs(String topic, Map<String, Object>...
filterProps);
/**
@@ -78,7 +86,9 @@ public interface JobStatusProvider {
* must match the template (AND query). By providing
several maps, different filters
* are possible (OR query).
* @return A non null collection.
+ * @deprecated Use {...@link #queryAllJobs(String, Map...)} instead.
*/
+ @Deprecated
Collection<Event> getAllJobs(String topic, Map<String, Object>...
filterProps);
/**
@@ -152,4 +162,40 @@ public interface JobStatusProvider {
* @param jobQueueName The name of the queue.
*/
void wakeUpJobQueue(final String jobQueueName);
+
+ /**
+ * Return a list of currently scheduled jobs.
+ * @param topic Topic can be used as a filter, if it is non-null, only
jobs with this topic will be returned.
+ * @param filterProps A list of filter property maps. Each map acts like a
template. The searched job
+ * must match the template (AND query). By providing
several maps, different filters
+ * are possible (OR query).
+ * @return A non null collection.
+ * @since 2.4
+ */
+ JobsIterator queryScheduledJobs(String topic, Map<String, Object>...
filterProps);
+
+ /**
+ * Return the jobs which are currently in processing. If there are several
application nodes
+ * in the cluster, there could be more than one job in processing
+ * @param topic Topic can be used as a filter, if it is non-null, only
jobs with this topic will be returned.
+ * @param filterProps A list of filter property maps. Each map acts like a
template. The searched job
+ * must match the template (AND query). By providing
several maps, different filters
+ * are possible (OR query).
+ * @return A non null collection.
+ * @since 2.4
+ */
+ JobsIterator queryCurrentJobs(String topic, Map<String, Object>...
filterProps);
+
+ /**
+ * Return all jobs either running or scheduled.
+ * This is actually a convenience method and collects the results from
{...@link #getScheduledJobs(String, Map...)}
+ * and {...@link #getCurrentJobs(String, Map...)}
+ * @param topic Topic can be used as a filter, if it is non-null, only
jobs with this topic will be returned.
+ * @param filterProps A list of filter property maps. Each map acts like a
template. The searched job
+ * must match the template (AND query). By providing
several maps, different filters
+ * are possible (OR query).
+ * @return A non null collection.
+ * @since 2.4
+ */
+ JobsIterator queryAllJobs(String topic, Map<String, Object>...
filterProps);
}
Added:
sling/trunk/bundles/extensions/event/src/main/java/org/apache/sling/event/JobsIterator.java
URL:
http://svn.apache.org/viewvc/sling/trunk/bundles/extensions/event/src/main/java/org/apache/sling/event/JobsIterator.java?rev=991134&view=auto
==============================================================================
---
sling/trunk/bundles/extensions/event/src/main/java/org/apache/sling/event/JobsIterator.java
(added)
+++
sling/trunk/bundles/extensions/event/src/main/java/org/apache/sling/event/JobsIterator.java
Tue Aug 31 09:50:02 2010
@@ -0,0 +1,62 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.sling.event;
+
+import java.util.Iterator;
+
+import org.osgi.service.event.Event;
+
+/**
+ * This <code>Iterator</code> allows to iterate over {...@link Event}s.
+ * In addition to an iterator it might return the number of elements
+ * in the collection and allows to skip several elements.
+ * If the iterator is not used to iterate through the whole collection
+ * of jobs, the {...@link #close()} method must be called in order to
+ * free resources!
+ */
+public interface JobsIterator extends Iterator<Event> {
+
+ /**
+ * Skip a number of jobs.
+ * @param skipNum the non-negative number of elements to skip
+ * @throws java.util.NoSuchElementException
+ * if skipped past the last job in the iterator.
+ */
+ void skip(long skipNum);
+
+ /**
+ * Returns the total number of jobs. In some cases a precise information
+ * is not available. In these cases -1 is returned.
+ */
+ long getSize();
+
+ /**
+ * Returns the current position within the iterator. The number returned is
+ * the 0-based index of the next job.
+ */
+ long getPosition();
+
+ /**
+ * Releases this iterators resources immediately instead of waiting for
this
+ * to happen when it is automatically closed. After a call to close, this
+ * iterator should not be used anymore.
+ * The iterator is closed automatically when it reaches it's end.
+ */
+ void close();
+}
Propchange:
sling/trunk/bundles/extensions/event/src/main/java/org/apache/sling/event/JobsIterator.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange:
sling/trunk/bundles/extensions/event/src/main/java/org/apache/sling/event/JobsIterator.java
------------------------------------------------------------------------------
svn:keywords = author date id revision rev url
Propchange:
sling/trunk/bundles/extensions/event/src/main/java/org/apache/sling/event/JobsIterator.java
------------------------------------------------------------------------------
svn:mime-type = text/plain
Modified:
sling/trunk/bundles/extensions/event/src/main/java/org/apache/sling/event/impl/AbstractRepositoryEventHandler.java
URL:
http://svn.apache.org/viewvc/sling/trunk/bundles/extensions/event/src/main/java/org/apache/sling/event/impl/AbstractRepositoryEventHandler.java?rev=991134&r1=991133&r2=991134&view=diff
==============================================================================
---
sling/trunk/bundles/extensions/event/src/main/java/org/apache/sling/event/impl/AbstractRepositoryEventHandler.java
(original)
+++
sling/trunk/bundles/extensions/event/src/main/java/org/apache/sling/event/impl/AbstractRepositoryEventHandler.java
Tue Aug 31 09:50:02 2010
@@ -290,9 +290,20 @@ public abstract class AbstractRepository
*/
protected Event readEvent(Node eventNode)
throws RepositoryException, ClassNotFoundException {
+ return this.readEvent(eventNode, false);
+ }
+
+ /**
+ * Read an event from the repository.
+ * @return
+ * @throws RepositoryException
+ * @throws ClassNotFoundException
+ */
+ protected Event readEvent(Node eventNode, final boolean forceLoad)
+ throws RepositoryException, ClassNotFoundException {
final String topic =
eventNode.getProperty(EventHelper.NODE_PROPERTY_TOPIC).getString();
final ClassLoader cl = this.getDynamicClassLoader();
- final Dictionary<String, Object> eventProps =
EventHelper.readEventProperties(eventNode, cl);
+ final Dictionary<String, Object> eventProps =
EventHelper.readEventProperties(eventNode, cl, forceLoad);
eventProps.put(JobStatusProvider.PROPERTY_EVENT_ID,
eventNode.getPath());
this.addEventProperties(eventNode, eventProps);
Modified:
sling/trunk/bundles/extensions/event/src/main/java/org/apache/sling/event/impl/EventHelper.java
URL:
http://svn.apache.org/viewvc/sling/trunk/bundles/extensions/event/src/main/java/org/apache/sling/event/impl/EventHelper.java?rev=991134&r1=991133&r2=991134&view=diff
==============================================================================
---
sling/trunk/bundles/extensions/event/src/main/java/org/apache/sling/event/impl/EventHelper.java
(original)
+++
sling/trunk/bundles/extensions/event/src/main/java/org/apache/sling/event/impl/EventHelper.java
Tue Aug 31 09:50:02 2010
@@ -251,7 +251,8 @@ public abstract class EventHelper {
* @throws ClassNotFoundException
*/
public static Dictionary<String, Object> readEventProperties(final Node
node,
- final
ClassLoader objectClassLoader)
+ final
ClassLoader objectClassLoader,
+ final boolean
forceLoad)
throws RepositoryException, ClassNotFoundException {
final Dictionary<String, Object> properties = new Hashtable<String,
Object>();
@@ -266,10 +267,18 @@ public abstract class EventHelper {
final Object value = ois.readObject();
properties.put(key, value);
}
+ } catch (ClassNotFoundException cnfe) {
+ if ( !forceLoad ) {
+ throw cnfe;
+ }
} catch (java.io.InvalidClassException ice) {
- throw new ClassNotFoundException("Found invalid class.", ice);
+ if ( !forceLoad ) {
+ throw new ClassNotFoundException("Found invalid class.",
ice);
+ }
} catch (IOException ioe) {
- throw new RepositoryException("Unable to deserialize event
properties.", ioe);
+ if ( !forceLoad ) {
+ throw new RepositoryException("Unable to deserialize event
properties.", ioe);
+ }
}
}
// now all properties that have been set directly
Modified:
sling/trunk/bundles/extensions/event/src/main/java/org/apache/sling/event/impl/JobEventHandler.java
URL:
http://svn.apache.org/viewvc/sling/trunk/bundles/extensions/event/src/main/java/org/apache/sling/event/impl/JobEventHandler.java?rev=991134&r1=991133&r2=991134&view=diff
==============================================================================
---
sling/trunk/bundles/extensions/event/src/main/java/org/apache/sling/event/impl/JobEventHandler.java
(original)
+++
sling/trunk/bundles/extensions/event/src/main/java/org/apache/sling/event/impl/JobEventHandler.java
Tue Aug 31 09:50:02 2010
@@ -59,9 +59,11 @@ import org.apache.sling.commons.threads.
import org.apache.sling.event.EventPropertiesMap;
import org.apache.sling.event.EventUtil;
import org.apache.sling.event.JobStatusProvider;
+import org.apache.sling.event.JobsIterator;
import org.apache.sling.event.impl.job.JobBlockingQueue;
import org.apache.sling.event.impl.job.JobStatusNotifier;
import org.apache.sling.event.impl.job.JobUtil;
+import org.apache.sling.event.impl.job.JobsIteratorImpl;
import org.apache.sling.event.impl.job.ParallelInfo;
import org.osgi.framework.Constants;
import org.osgi.service.component.ComponentConstants;
@@ -1104,6 +1106,29 @@ public class JobEventHandler
}
/**
+ * Read an event from the repository.
+ * This method is similar as {...@link #readEvent(Node)} with the exception
+ * that it even loads the event if classes are missing
+ * @throws RepositoryException
+ */
+ public Event forceReadEvent(Node eventNode)
+ throws RepositoryException {
+ try {
+ return this.readEvent(eventNode);
+ } catch (ClassNotFoundException cnfe) {
+ this.ignoreException(cnfe);
+ }
+ // we try it again and set the force load flag
+ try {
+ return this.readEvent(eventNode, true);
+ } catch (ClassNotFoundException cnfe) {
+ // this can never happen but we catch it anyway and rethrow
+ this.ignoreException(cnfe);
+ throw new RepositoryException(cnfe);
+ }
+ }
+
+ /**
* @see
javax.jcr.observation.EventListener#onEvent(javax.jcr.observation.EventIterator)
*/
public void onEvent(EventIterator iter) {
@@ -1513,12 +1538,12 @@ public class JobEventHandler
* @return
* @throws RepositoryException
*/
- private Collection<Event> queryJobs(final String topic,
- final Boolean locked,
- final Map<String, Object>...
filterProps) {
+ private JobsIterator queryJobs(final String topic,
+ final Boolean locked,
+ final Map<String, Object>... filterProps) {
// we create a new session
Session s = null;
- final List<Event> jobs = new ArrayList<Event>();
+ boolean closeSession = true;
try {
s = this.createSession();
final QueryManager qManager = s.getWorkspace().getQueryManager();
@@ -1591,30 +1616,34 @@ public class JobEventHandler
}
final NodeIterator iter = q.execute().getNodes();
- while ( iter.hasNext() ) {
- final Node eventNode = iter.nextNode();
- try {
- final Event event = this.readEvent(eventNode);
- jobs.add(event);
- } catch (ClassNotFoundException cnfe) {
- // in the case of a class not found exception we just
ignore the exception
- this.ignoreException(cnfe);
- }
- }
+ closeSession = false;
+ return new JobsIteratorImpl(iter, s, this);
} catch (RepositoryException e) {
// in the case of an error, we return an empty list
this.ignoreException(e);
} finally {
- if ( s != null) {
+ if ( s != null && closeSession) {
s.logout();
}
}
+ return new JobsIteratorImpl(null, null, null);
+ }
+
+ private Collection<Event> queryJobsAsList(final String topic,
+ final Boolean locked,
+ final Map<String, Object>... filterProps) {
+ final JobsIterator ji = this.queryJobs(topic, locked, filterProps);
+ final List<Event> jobs = new ArrayList<Event>();
+ while ( ji.hasNext() ) {
+ jobs.add(ji.next());
+ }
return jobs;
}
/**
* @see
org.apache.sling.event.JobStatusProvider#getCurrentJobs(java.lang.String)
*/
+ @Deprecated
public Collection<Event> getCurrentJobs(String topic) {
return this.getCurrentJobs(topic, (Map<String, Object>[])null);
}
@@ -1622,6 +1651,7 @@ public class JobEventHandler
/**
* @see
org.apache.sling.event.JobStatusProvider#getScheduledJobs(java.lang.String)
*/
+ @Deprecated
public Collection<Event> getScheduledJobs(String topic) {
return this.getScheduledJobs(topic, (Map<String, Object>[])null);
}
@@ -1629,26 +1659,28 @@ public class JobEventHandler
/**
* @see
org.apache.sling.event.JobStatusProvider#getCurrentJobs(java.lang.String,
java.util.Map...)
*/
+ @Deprecated
public Collection<Event> getCurrentJobs(String topic, Map<String,
Object>... filterProps) {
- return this.queryJobs(topic, true, filterProps);
+ return this.queryJobsAsList(topic, true, filterProps);
}
/**
* @see
org.apache.sling.event.JobStatusProvider#getScheduledJobs(java.lang.String,
java.util.Map...)
*/
+ @Deprecated
public Collection<Event> getScheduledJobs(String topic, Map<String,
Object>... filterProps) {
- return this.queryJobs(topic, false, filterProps);
+ return this.queryJobsAsList(topic, false, filterProps);
}
/**
* @see
org.apache.sling.event.JobStatusProvider#getAllJobs(java.lang.String,
java.util.Map...)
*/
+ @Deprecated
public Collection<Event> getAllJobs(String topic, Map<String, Object>...
filterProps) {
- return this.queryJobs(topic, null, filterProps);
+ return this.queryJobsAsList(topic, null, filterProps);
}
-
/**
* @see
org.apache.sling.event.JobStatusProvider#cancelJob(java.lang.String,
java.lang.String)
*/
@@ -1696,7 +1728,7 @@ public class JobEventHandler
if ( this.backgroundSession.itemExists(jobId) ) {
final Node eventNode = (Node)
this.backgroundSession.getItem(jobId);
if ( eventNode.isLocked() ) {
- this.logger.info("Attempted to cancel a running
job at {}", jobId);
+ this.logger.debug("Attempted to cancel a running
job at {}", jobId);
return false;
}
// try to load job to send notification
@@ -1790,6 +1822,27 @@ public class JobEventHandler
}
}
+ /**
+ * @see org.apache.sling.event.JobStatusProvider#queryAllJobs(String,
Map...)
+ */
+ public JobsIterator queryAllJobs(final String topic, final Map<String,
Object>... filterProps) {
+ return this.queryJobs(topic, null, filterProps);
+ }
+
+ /**
+ * @see org.apache.sling.event.JobStatusProvider#queryCurrentJobs(String,
Map...)
+ */
+ public JobsIterator queryCurrentJobs(final String topic, final Map<String,
Object>... filterProps) {
+ return this.queryJobs(topic, true, filterProps);
+ }
+
+ /**
+ * @see
org.apache.sling.event.JobStatusProvider#queryScheduledJobs(String, Map...)
+ */
+ public JobsIterator queryScheduledJobs(final String topic, final
Map<String, Object>... filterProps) {
+ return this.queryJobs(topic, false, filterProps);
+ }
+
private static final class StartedJobInfo {
public final Event event;
public final String nodePath;
Added:
sling/trunk/bundles/extensions/event/src/main/java/org/apache/sling/event/impl/job/JobsIteratorImpl.java
URL:
http://svn.apache.org/viewvc/sling/trunk/bundles/extensions/event/src/main/java/org/apache/sling/event/impl/job/JobsIteratorImpl.java?rev=991134&view=auto
==============================================================================
---
sling/trunk/bundles/extensions/event/src/main/java/org/apache/sling/event/impl/job/JobsIteratorImpl.java
(added)
+++
sling/trunk/bundles/extensions/event/src/main/java/org/apache/sling/event/impl/job/JobsIteratorImpl.java
Tue Aug 31 09:50:02 2010
@@ -0,0 +1,115 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.sling.event.impl.job;
+
+import java.util.NoSuchElementException;
+
+import javax.jcr.Node;
+import javax.jcr.NodeIterator;
+import javax.jcr.RepositoryException;
+import javax.jcr.Session;
+
+import org.apache.sling.event.JobsIterator;
+import org.apache.sling.event.impl.JobEventHandler;
+import org.osgi.service.event.Event;
+
+/**
+ * JCR Based Implementation of the jobs iterator
+ */
+public class JobsIteratorImpl implements JobsIterator {
+
+ private NodeIterator delegatee;
+
+ private Session session;
+
+ private JobEventHandler handler;
+
+ public JobsIteratorImpl(final NodeIterator ni,
+ final Session session,
+ final JobEventHandler handler) {
+ this.delegatee = ni;
+ this.session = session;
+ this.handler = handler;
+ }
+
+ /**
+ * @see org.apache.sling.event.JobsIterator#close()
+ */
+ public void close() {
+ if ( this.session != null ) {
+ this.session.logout();
+ this.session = null;
+ this.delegatee = null;
+ this.handler = null;
+ }
+ }
+
+ /**
+ * @see org.apache.sling.event.JobsIterator#getPosition()
+ */
+ public long getPosition() {
+ return this.delegatee.getPosition();
+ }
+
+ /**
+ * @see org.apache.sling.event.JobsIterator#getSize()
+ */
+ public long getSize() {
+ return this.delegatee.getSize();
+ }
+
+ /**
+ * @see org.apache.sling.event.JobsIterator#skip(long)
+ */
+ public void skip(long skipNum) {
+ this.delegatee.skip(skipNum);
+ }
+
+ /**
+ * @see java.util.Iterator#hasNext()
+ */
+ public boolean hasNext() {
+ final boolean result = (this.delegatee == null ? false :
this.delegatee.hasNext());
+ if ( !result ) {
+ this.close();
+ }
+ return result;
+ }
+
+ /**
+ * @see java.util.Iterator#next()
+ */
+ public Event next() {
+ final Node n = this.delegatee.nextNode();
+ try {
+ return this.handler.forceReadEvent(n);
+ } catch (RepositoryException e) {
+ // if something goes wrong, we shutdown the iterator
+ this.close();
+ throw (NoSuchElementException)new
NoSuchElementException("Repository exception during job reading").initCause(e);
+ }
+ }
+
+ /**
+ * @see java.util.Iterator#remove()
+ */
+ public void remove() {
+ throw new UnsupportedOperationException("Remove not supported.");
+ }
+}
Propchange:
sling/trunk/bundles/extensions/event/src/main/java/org/apache/sling/event/impl/job/JobsIteratorImpl.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange:
sling/trunk/bundles/extensions/event/src/main/java/org/apache/sling/event/impl/job/JobsIteratorImpl.java
------------------------------------------------------------------------------
svn:keywords = author date id revision rev url
Propchange:
sling/trunk/bundles/extensions/event/src/main/java/org/apache/sling/event/impl/job/JobsIteratorImpl.java
------------------------------------------------------------------------------
svn:mime-type = text/plain