incubator-sling-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From bdelacre...@apache.org
Subject svn commit: r964041 - in /sling/trunk/contrib/extensions/bgservlets/src: main/java/org/apache/sling/bgservlets/impl/ main/java/org/apache/sling/bgservlets/impl/webconsole/ test/java/org/apache/sling/bgservlets/impl/
Date Wed, 14 Jul 2010 13:24:08 GMT
Author: bdelacretaz
Date: Wed Jul 14 13:24:08 2010
New Revision: 964041

URL: http://svn.apache.org/viewvc?rev=964041&view=rev
Log:
SLING-550 - suspend/resume/stop jobs from webconsole, work in progress

Modified:
    sling/trunk/contrib/extensions/bgservlets/src/main/java/org/apache/sling/bgservlets/impl/BackgroundTestServlet.java
    sling/trunk/contrib/extensions/bgservlets/src/main/java/org/apache/sling/bgservlets/impl/FilterChainExecutionJob.java
    sling/trunk/contrib/extensions/bgservlets/src/main/java/org/apache/sling/bgservlets/impl/ServletResponseWrapper.java
    sling/trunk/contrib/extensions/bgservlets/src/main/java/org/apache/sling/bgservlets/impl/SuspendableOutputStream.java
    sling/trunk/contrib/extensions/bgservlets/src/main/java/org/apache/sling/bgservlets/impl/webconsole/ExecutionEngineConsolePlugin.java
    sling/trunk/contrib/extensions/bgservlets/src/test/java/org/apache/sling/bgservlets/impl/SuspendableOutputStreamTest.java

Modified: sling/trunk/contrib/extensions/bgservlets/src/main/java/org/apache/sling/bgservlets/impl/BackgroundTestServlet.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/bgservlets/src/main/java/org/apache/sling/bgservlets/impl/BackgroundTestServlet.java?rev=964041&r1=964040&r2=964041&view=diff
==============================================================================
--- sling/trunk/contrib/extensions/bgservlets/src/main/java/org/apache/sling/bgservlets/impl/BackgroundTestServlet.java
(original)
+++ sling/trunk/contrib/extensions/bgservlets/src/main/java/org/apache/sling/bgservlets/impl/BackgroundTestServlet.java
Wed Jul 14 13:24:08 2010
@@ -29,6 +29,8 @@ import org.apache.felix.scr.annotations.
 import org.apache.sling.api.SlingHttpServletRequest;
 import org.apache.sling.api.SlingHttpServletResponse;
 import org.apache.sling.api.servlets.SlingSafeMethodsServlet;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 /** Servlet used for interactive testing of the background
  * 	servlets engine.
@@ -40,6 +42,8 @@ import org.apache.sling.api.servlets.Sli
 @Property(name="sling.servlet.paths", value="/system/bgservlets/test")
 public class BackgroundTestServlet extends SlingSafeMethodsServlet {
 
+	private final Logger log = LoggerFactory.getLogger(getClass());
+	
 	@Override
 	protected void doGet(SlingHttpServletRequest request,
 			SlingHttpServletResponse response) throws ServletException,
@@ -51,20 +55,24 @@ public class BackgroundTestServlet exten
 		final int interval = getIntParam(request, "interval", 1);
 		final int flushEvery = getIntParam(request, "flushEvery", 2);
 		
-		for(int i=1; i <= cycles; i++) {
-			if(i % flushEvery == 0) {
-				w.println("Flushing output");
-				w.flush();
-			}
-			w.printf("Cycle %d of %d\n", i, cycles);
-			try {
-				Thread.sleep(interval * 1000);
-			} catch(InterruptedException iex) {
-				throw new ServletException("InterruptedException", iex);
+		try {
+			for(int i=1; i <= cycles; i++) {
+				if(i % flushEvery == 0) {
+					w.println("Flushing output");
+					w.flush();
+				}
+				w.printf("Cycle %d of %d\n", i, cycles);
+				try {
+					Thread.sleep(interval * 1000);
+				} catch(InterruptedException iex) {
+					throw new ServletException("InterruptedException", iex);
+				}
 			}
+			w.println("All done.");
+			w.flush();
+		} catch(Throwable t) {
+			log.info("Exception in doGet", t);
 		}
-		w.println("All done.");
-		w.flush();
 	}
 	
 	private int getIntParam(SlingHttpServletRequest request, String name, int defaultValue)
{

Modified: sling/trunk/contrib/extensions/bgservlets/src/main/java/org/apache/sling/bgservlets/impl/FilterChainExecutionJob.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/bgservlets/src/main/java/org/apache/sling/bgservlets/impl/FilterChainExecutionJob.java?rev=964041&r1=964040&r2=964041&view=diff
==============================================================================
--- sling/trunk/contrib/extensions/bgservlets/src/main/java/org/apache/sling/bgservlets/impl/FilterChainExecutionJob.java
(original)
+++ sling/trunk/contrib/extensions/bgservlets/src/main/java/org/apache/sling/bgservlets/impl/FilterChainExecutionJob.java
Wed Jul 14 13:24:08 2010
@@ -18,6 +18,8 @@
  */
 package org.apache.sling.bgservlets.impl;
 
+import java.io.File;
+import java.io.FileOutputStream;
 import java.io.IOException;
 
 import javax.servlet.FilterChain;
@@ -35,8 +37,8 @@ class FilterChainExecutionJob implements
 	private final Logger log = LoggerFactory.getLogger(getClass());
 	private final FilterChain chain;
 	private final ServletResponseWrapper response;
+	private final SuspendableOutputStream stream;
 	private final String path;
-	private State state = State.NEW;
 	
 	// TODO is it ok to keep a reference to the request until run() is called??
 	private final HttpServletRequest request;
@@ -44,12 +46,17 @@ class FilterChainExecutionJob implements
 	FilterChainExecutionJob(FilterChain chain, HttpServletRequest request, HttpServletResponse
hsr) throws IOException {
 		this.chain = chain;
 		this.request = request;
-		response  = new ServletResponseWrapper(hsr);
-		path = response.getOutputPath();
+		
+		// TODO write output to the Sling repository. For now: just a temp file
+		final File output = File.createTempFile(getClass().getSimpleName(), ".data");
+		output.deleteOnExit();
+		path = output.getAbsolutePath();
+		stream = new SuspendableOutputStream(new FileOutputStream(output));
+		response  = new ServletResponseWrapper(hsr, stream);
 	}
 	
 	public String toString() {
-		return getClass().getSimpleName() + ", state=" + state + ", path=" + path;
+		return getClass().getSimpleName() + ", state=" + getState() + ", path=" + path;
 	}
 	
 	public void run() {
@@ -73,11 +80,10 @@ class FilterChainExecutionJob implements
 	}
 
 	public State getState() {
-		return state;
+		return stream.getState();
 	}
 
 	public void requestStateChange(State s) {
-		// TODO need some validity checks
-		state = s;
+		stream.requestStateChange(s);
 	}
 }

Modified: sling/trunk/contrib/extensions/bgservlets/src/main/java/org/apache/sling/bgservlets/impl/ServletResponseWrapper.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/bgservlets/src/main/java/org/apache/sling/bgservlets/impl/ServletResponseWrapper.java?rev=964041&r1=964040&r2=964041&view=diff
==============================================================================
--- sling/trunk/contrib/extensions/bgservlets/src/main/java/org/apache/sling/bgservlets/impl/ServletResponseWrapper.java
(original)
+++ sling/trunk/contrib/extensions/bgservlets/src/main/java/org/apache/sling/bgservlets/impl/ServletResponseWrapper.java
Wed Jul 14 13:24:08 2010
@@ -18,8 +18,6 @@
  */
 package org.apache.sling.bgservlets.impl;
 
-import java.io.File;
-import java.io.FileOutputStream;
 import java.io.IOException;
 import java.io.OutputStream;
 import java.io.OutputStreamWriter;
@@ -32,15 +30,14 @@ import javax.servlet.http.HttpServletRes
 /** Wraps an HttpServletResponse for background processing */
 class ServletResponseWrapper extends HttpServletResponseWrapper {
 
-	private final String outputPath;
 	private final ServletOutputStream stream;
 	private final PrintWriter writer;
 	
-	static class CustomOutputStream extends ServletOutputStream {
+	static class ServletOutputStreamWrapper extends ServletOutputStream {
 
 		private final OutputStream os;
 		
-		CustomOutputStream(OutputStream os) {
+		ServletOutputStreamWrapper(OutputStream os) {
 			this.os = os;
 		}
 		
@@ -61,24 +58,12 @@ class ServletResponseWrapper extends Htt
 		
 	}
 	
-	ServletResponseWrapper(HttpServletResponse response) throws IOException {
+	ServletResponseWrapper(HttpServletResponse response, OutputStream os) throws IOException
{
 		super(response);
-		// TODO write output to the Sling repository. For now: just a temp file
-		final File output = File.createTempFile(getClass().getSimpleName(), ".data");
-		output.deleteOnExit();
-		outputPath = output.getAbsolutePath();
-		stream = new CustomOutputStream(new FileOutputStream(output));
+		stream = new ServletOutputStreamWrapper(os);
 		writer = new PrintWriter(new OutputStreamWriter(stream));
 	}
 	
-	public String toString() {
-		return getClass().getName() + ":" + outputPath;
-	}
-	
-	String getOutputPath() {
-		return outputPath;
-	}
-	
 	void cleanup() throws IOException {
 		stream.flush();
 		stream.close();

Modified: sling/trunk/contrib/extensions/bgservlets/src/main/java/org/apache/sling/bgservlets/impl/SuspendableOutputStream.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/bgservlets/src/main/java/org/apache/sling/bgservlets/impl/SuspendableOutputStream.java?rev=964041&r1=964040&r2=964041&view=diff
==============================================================================
--- sling/trunk/contrib/extensions/bgservlets/src/main/java/org/apache/sling/bgservlets/impl/SuspendableOutputStream.java
(original)
+++ sling/trunk/contrib/extensions/bgservlets/src/main/java/org/apache/sling/bgservlets/impl/SuspendableOutputStream.java
Wed Jul 14 13:24:08 2010
@@ -30,11 +30,11 @@ import org.apache.sling.bgservlets.JobSt
  * 	stream) or stop them (by throwing an exception).
  */
 public class SuspendableOutputStream extends FilterOutputStream implements JobStatus {
-	private State state = State.RUNNING;
+	private State state = State.NEW;
 	private boolean closed = false;
 	
 	@SuppressWarnings("serial")
-	public static class StreamStoppedException extends IOException {
+	public static class StreamStoppedException extends RuntimeException {
 		StreamStoppedException() {
 			super("Stopped by " + SuspendableOutputStream.class.getSimpleName());
 		}
@@ -86,7 +86,9 @@ public class SuspendableOutputStream ext
 					state = State.SUSPENDED;
 					try {
 						// suspended: block until resumed
-						wait();
+						while(state == State.SUSPENDED) {
+							wait();
+						}
 					} catch (InterruptedException e) {
 						throw new IOException("InterruptedException in checkWritePermission()", e);
 					}
@@ -103,9 +105,12 @@ public class SuspendableOutputStream ext
 	public synchronized void requestStateChange(State s) {
 		boolean illegal = false;
 		
-		if(s == State.SUSPENDED) {
-			if(state == State.RUNNING) {
+		if(state == State.DONE) {
+			// ignore changes
+		} else if(s == State.SUSPENDED) {
+			if(state == State.NEW || state == State.QUEUED || state == State.RUNNING) {
 				state = State.SUSPEND_REQUESTED;
+				notify();
 			} else if(state == State.SUSPEND_REQUESTED || state == State.SUSPENDED) {
 				// ignore change
 			} else {
@@ -113,8 +118,10 @@ public class SuspendableOutputStream ext
 			}
 			
 		} else if(s == State.STOPPED) {
-			if(state == State.RUNNING) {
+			if(state == State.NEW || state == State.QUEUED || state == State.RUNNING 
+					|| state == State.SUSPEND_REQUESTED || state == State.SUSPENDED) {
 				state = State.STOP_REQUESTED;
+				notify();
 			} else if (state == State.STOP_REQUESTED || state == State.STOPPED) {
 				// ignore change
 			} else {
@@ -126,6 +133,10 @@ public class SuspendableOutputStream ext
 				state = State.RUNNING;
 				notify();
 			}
+			
+		} else {
+			state = s;
+			notify();
 		}
 		
 		if(illegal) {

Modified: sling/trunk/contrib/extensions/bgservlets/src/main/java/org/apache/sling/bgservlets/impl/webconsole/ExecutionEngineConsolePlugin.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/bgservlets/src/main/java/org/apache/sling/bgservlets/impl/webconsole/ExecutionEngineConsolePlugin.java?rev=964041&r1=964040&r2=964041&view=diff
==============================================================================
--- sling/trunk/contrib/extensions/bgservlets/src/main/java/org/apache/sling/bgservlets/impl/webconsole/ExecutionEngineConsolePlugin.java
(original)
+++ sling/trunk/contrib/extensions/bgservlets/src/main/java/org/apache/sling/bgservlets/impl/webconsole/ExecutionEngineConsolePlugin.java
Wed Jul 14 13:24:08 2010
@@ -106,6 +106,7 @@ public class ExecutionEngineConsolePlugi
         public String getTitle() {
             return TITLE;
         }
+        
         @Override
         protected void renderContent(HttpServletRequest req, HttpServletResponse res)
           throws ServletException, IOException {
@@ -115,17 +116,65 @@ public class ExecutionEngineConsolePlugi
         		pw.println("No ExecutionEngine service found");
         		return;
         	}
+        	
+        	// TODO should use POST
+    		final String jobPath = req.getParameter("jobPath");
+    		if(jobPath != null) {
+        		final JobStatus job = ee.getJobStatus(jobPath);
+        		if(job != null) {
+            		final String action = req.getParameter("action");
+            		if("suspend".equals(action)) {
+            			job.requestStateChange(JobStatus.State.SUSPENDED);
+            		} else if("stop".equals(action)) {
+            			job.requestStateChange(JobStatus.State.STOPPED);
+            		} else if("resume".equals(action)) {
+            			job.requestStateChange(JobStatus.State.RUNNING);
+            		}
+        		}
+    		}
+    		
+    		pw.println("TODO: provide a way to cleanup old jobs<br/>");
+    		pw.println("TODO: optionally list active jobs only<br/>");
   
-        	pw.println("ExecutionEngine jobs:<br/>");
-        	pw.println("<pre>");
+            pw.println("<table class='content' cellpadding='0' cellspacing='0' width='100%'>");
+            pw.println("<thead>");
+            pw.println("<tr class='content'>");
+            pw.println("<th class='content container'>Controls</th>");
+            pw.println("<th class='content container'>State</th>");
+            pw.println("<th class='content container'>Path</th>");
+            pw.println("</tr>");
+            pw.println("</thead>");
+            pw.println("<tbody>");
+
         	final Iterator<JobStatus> it = ee.getMatchingJobStatus(null);
         	int count = 0;
         	while(it.hasNext()) {
-        		pw.println(it.next());
+        		renderJobStatus(pw, it.next());
         		count++;
         	}
-        	pw.println("</pre>");
+            pw.println("</tbody>");
+        	pw.println("</table>");
         	pw.println("Total <b>" + count + "</b> jobs.<br />");
         }
+        
+        private void renderJobStatus(PrintWriter pw, JobStatus job) {
+        	// TODO should use POST
+            pw.println("<tr class='content'>");
+        	pw.println("<td><form action='./" + LABEL + "' method='GET'>");
+        	final String [] actions = { "suspend", "resume", "stop" };
+        	for(String action : actions) {
+        		pw.println("<input type='submit' name='action' value='" + action + "'/>&nbsp;");
+        	}
+        	pw.println("<input type='hidden' name='jobPath' value='" + job.getPath() + "'/>&nbsp;");
+        	pw.println("</form></td>");
+        	pw.println("<td>");
+        	pw.println(job.getState());
+        	pw.println("</td>");
+        	pw.println("<td>");
+        	pw.println(job.getPath());
+        	pw.println("</td>");
+        	pw.println("</tr>");
+        }
+    
     }
 }
\ No newline at end of file

Modified: sling/trunk/contrib/extensions/bgservlets/src/test/java/org/apache/sling/bgservlets/impl/SuspendableOutputStreamTest.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/bgservlets/src/test/java/org/apache/sling/bgservlets/impl/SuspendableOutputStreamTest.java?rev=964041&r1=964040&r2=964041&view=diff
==============================================================================
--- sling/trunk/contrib/extensions/bgservlets/src/test/java/org/apache/sling/bgservlets/impl/SuspendableOutputStreamTest.java
(original)
+++ sling/trunk/contrib/extensions/bgservlets/src/test/java/org/apache/sling/bgservlets/impl/SuspendableOutputStreamTest.java
Wed Jul 14 13:24:08 2010
@@ -70,7 +70,8 @@ public class SuspendableOutputStreamTest
 	public void testStop() throws IOException {
 		final ByteArrayOutputStream bos = new ByteArrayOutputStream();
 		final SuspendableOutputStream f = new SuspendableOutputStream(bos);
-		assertEquals("Expecting RUNNING state first", JobStatus.State.RUNNING, f.getState());
+		assertEquals("Expecting NEW state first", JobStatus.State.NEW, f.getState());
+		f.requestStateChange(JobStatus.State.RUNNING);
 		f.write(TEST.getBytes());
 		f.flush();
 		
@@ -89,6 +90,7 @@ public class SuspendableOutputStreamTest
 	public void testSuspend() throws Exception {
 		final ByteArrayOutputStream bos = new ByteArrayOutputStream();
 		final SuspendableOutputStream f = new SuspendableOutputStream(bos);
+		f.requestStateChange(JobStatus.State.RUNNING);
 		final WriterThread t = new WriterThread(f);
 		t.setDaemon(true);
 		t.start();
@@ -116,4 +118,43 @@ public class SuspendableOutputStreamTest
 		assertNotNull("Expecting non-null Exception in WriterThread", t.runException);
 		assertTrue("Expecting IOException in WriterThread", t.runException instanceof IOException);
 	}
+	
+	@Test
+	public void testSuspendThenStop() throws Exception {
+		final ByteArrayOutputStream bos = new ByteArrayOutputStream();
+		final SuspendableOutputStream f = new SuspendableOutputStream(bos);
+		assertEquals("Expecting NEW state first", JobStatus.State.NEW, f.getState());
+		final WriterThread t = new WriterThread(f);
+		t.setDaemon(true);
+		t.start();
+		
+		f.requestStateChange(JobStatus.State.SUSPENDED);
+		
+		final long delay = WriterThread.WRITE_DELAY * 3;
+		Thread.sleep(delay);
+		assertEquals("Expecting SUSPEND state after a few writes", JobStatus.State.SUSPENDED, f.getState());
+		
+		f.requestStateChange(JobStatus.State.STOPPED);
+		assertEquals("Expecting STOP_REQUESTED state before write", JobStatus.State.STOP_REQUESTED,
f.getState());
+		try {
+			f.write("nothing".getBytes());
+			fail("Expected StreamStoppedException when writing to STOPPED stream");
+		} catch(SuspendableOutputStream.StreamStoppedException asExpected) {
+		}
+		
+		assertEquals("Expecting STOPPED state after write", JobStatus.State.STOPPED, f.getState());
+		f.close();
+	}
+	
+	@Test
+	public void testDone() {
+		final ByteArrayOutputStream bos = new ByteArrayOutputStream();
+		final SuspendableOutputStream f = new SuspendableOutputStream(bos);
+		f.requestStateChange(JobStatus.State.DONE);
+		assertEquals("Expecting DONE state (1)", JobStatus.State.DONE, f.getState());
+		f.requestStateChange(JobStatus.State.SUSPENDED);
+		assertEquals("Expecting DONE state (2)", JobStatus.State.DONE, f.getState());
+		f.requestStateChange(JobStatus.State.STOPPED);
+		assertEquals("Expecting DONE state (3)", JobStatus.State.DONE, f.getState());
+	}
 }



Mime
View raw message