From: Mathieu Baudier Date: Wed, 10 Jun 2009 15:03:46 +0000 (+0000) Subject: Improve SystemCall X-Git-Tag: argeo-slc-2.1.7~1805 X-Git-Url: http://git.argeo.org/?a=commitdiff_plain;h=719f374a748e531ae706115252978e06ad72c308;p=gpl%2Fargeo-slc.git Improve SystemCall Reactivate SlcExecutionStep git-svn-id: https://svn.argeo.org/slc/trunk@2524 4cfe0d0a-d680-48aa-b62c-e0a02a3f76cc --- diff --git a/demo/pom.xml b/demo/pom.xml index d9d0a0d8d..27e7888d0 100644 --- a/demo/pom.xml +++ b/demo/pom.xml @@ -146,6 +146,13 @@ + + + org.argeo.slc.dep + org.argeo.slc.dep.server + ${project.version} + + server_mysql diff --git a/integration-tests/org.argeo.slc.it.webapp/pom.xml b/integration-tests/org.argeo.slc.it.webapp/pom.xml index ef2287379..aa25a83be 100644 --- a/integration-tests/org.argeo.slc.it.webapp/pom.xml +++ b/integration-tests/org.argeo.slc.it.webapp/pom.xml @@ -31,19 +31,12 @@ ${basedir}/../../server/org.argeo.slc.siteserver/bundles;in=* - org.argeo.dep.osgi.catalina.start, org.springframework.osgi.extender, - org.springframework.osgi.web.extender, - org.springframework.osgi.samples.simplewebapp, - org.argeo.slc.server.activemq, + org.argeo.slc.server.main, org.argeo.slc.server.hsqldb, - org.argeo.slc.server.hibernate, - org.argeo.slc.server.services, - org.argeo.slc.server.jms, - org.argeo.slc.webapp, org.argeo.slc.ria, org.argeo.slc.agent - + diff --git a/runtime/org.argeo.slc.server/src/main/java/org/argeo/slc/services/ServiceMsgHandler.java b/runtime/org.argeo.slc.server/src/main/java/org/argeo/slc/services/ServiceMsgHandler.java index 4bf96d6c1..2ec840962 100644 --- a/runtime/org.argeo.slc.server/src/main/java/org/argeo/slc/services/ServiceMsgHandler.java +++ b/runtime/org.argeo.slc.server/src/main/java/org/argeo/slc/services/ServiceMsgHandler.java @@ -3,6 +3,7 @@ package org.argeo.slc.services; import org.argeo.slc.SlcException; import org.argeo.slc.msg.MsgHandler; import org.argeo.slc.msg.process.SlcExecutionStatusRequest; +import org.argeo.slc.msg.process.SlcExecutionStepsRequest; import org.argeo.slc.msg.test.tree.AddTreeTestResultAttachmentRequest; import org.argeo.slc.msg.test.tree.CloseTreeTestResultRequest; import org.argeo.slc.msg.test.tree.CreateTreeTestResultRequest; @@ -18,6 +19,8 @@ public class ServiceMsgHandler implements MsgHandler { public Object handleMsg(Object msg) { if (msg instanceof SlcExecution) slcExecutionService.newExecution((SlcExecution) msg); + else if (msg instanceof SlcExecutionStepsRequest) + slcExecutionService.addSteps((SlcExecutionStepsRequest) msg); else if (msg instanceof SlcExecutionStatusRequest) slcExecutionService.updateStatus((SlcExecutionStatusRequest) msg); else if (msg instanceof CreateTreeTestResultRequest) diff --git a/runtime/org.argeo.slc.server/src/main/java/org/argeo/slc/services/impl/process/SlcExecutionServiceImpl.java b/runtime/org.argeo.slc.server/src/main/java/org/argeo/slc/services/impl/process/SlcExecutionServiceImpl.java index b3c6f71fc..1cb71070f 100644 --- a/runtime/org.argeo.slc.server/src/main/java/org/argeo/slc/services/impl/process/SlcExecutionServiceImpl.java +++ b/runtime/org.argeo.slc.server/src/main/java/org/argeo/slc/services/impl/process/SlcExecutionServiceImpl.java @@ -5,7 +5,9 @@ import org.apache.commons.logging.LogFactory; import org.argeo.slc.SlcException; import org.argeo.slc.dao.process.SlcExecutionDao; import org.argeo.slc.msg.process.SlcExecutionStatusRequest; +import org.argeo.slc.msg.process.SlcExecutionStepsRequest; import org.argeo.slc.process.SlcExecution; +import org.argeo.slc.process.SlcExecutionStep; import org.argeo.slc.services.process.SlcExecutionService; public class SlcExecutionServiceImpl implements SlcExecutionService { @@ -27,11 +29,14 @@ public class SlcExecutionServiceImpl implements SlcExecutionService { slcExecutionDao.create(slcExecutionMsg); } else { - if (log.isTraceEnabled()) - log.trace("Updating SLC execution #" - + slcExecutionMsg.getUuid()); - - slcExecutionDao.merge(slcExecutionMsg); + throw new SlcException( + "There is already an SlcExecution registered with id " + + slcExecutionMsg.getUuid()); + // if (log.isTraceEnabled()) + // log.trace("Updating SLC execution #" + // + slcExecutionMsg.getUuid()); + // + // slcExecutionDao.merge(slcExecutionMsg); } } @@ -44,10 +49,21 @@ public class SlcExecutionServiceImpl implements SlcExecutionService { slcExecution.setStatus(msg.getNewStatus()); + if (msg.getNewStatus().equals(SlcExecution.STATUS_FINISHED)) + slcExecution.getSteps().add( + new SlcExecutionStep(SlcExecutionStep.TYPE_END, + "Process finished.")); + if (log.isTraceEnabled()) log.trace("Updating status for SLC execution #" - + slcExecution.getUuid()); + + slcExecution.getUuid() + " to status " + + msg.getNewStatus()); slcExecutionDao.update(slcExecution); } + + public void addSteps(SlcExecutionStepsRequest msg) { + slcExecutionDao.addSteps(msg.getSlcExecutionUuid(), msg.getSteps()); + } + } diff --git a/runtime/org.argeo.slc.server/src/main/java/org/argeo/slc/services/impl/test/TestManagerServiceImpl.java b/runtime/org.argeo.slc.server/src/main/java/org/argeo/slc/services/impl/test/TestManagerServiceImpl.java index 7ccc35d11..59b7b37db 100644 --- a/runtime/org.argeo.slc.server/src/main/java/org/argeo/slc/services/impl/test/TestManagerServiceImpl.java +++ b/runtime/org.argeo.slc.server/src/main/java/org/argeo/slc/services/impl/test/TestManagerServiceImpl.java @@ -16,7 +16,9 @@ import org.argeo.slc.process.SlcExecution; import org.argeo.slc.services.test.TestManagerService; import org.argeo.slc.test.TestRunDescriptor; -/** Implementation of complex operations impacting the underlying data. */ +/** + * Implementation of complex operations impacting the underlying data. + */ public class TestManagerServiceImpl implements TestManagerService { private Log log = LogFactory.getLog(getClass()); @@ -57,9 +59,9 @@ public class TestManagerServiceImpl implements TestManagerService { .getTestResultUuid()); } } else { - log - .trace("ResultUUID=" - + testRunDescriptor.getTestResultUuid()); + if (log.isTraceEnabled()) + log.trace("ResultUUID=" + + testRunDescriptor.getTestResultUuid()); addResultToCollection("default", testRunDescriptor .getTestResultUuid()); } @@ -67,6 +69,7 @@ public class TestManagerServiceImpl implements TestManagerService { } public void addResultToCollection(String collectionId, String resultUuid) { + // TODO: improve collections TreeTestResultCollection ttrc = treeTestResultCollectionDao .getTestResultCollection(collectionId); if (ttrc == null) { @@ -100,6 +103,11 @@ public class TestManagerServiceImpl implements TestManagerService { treeTestResultDao.create(treeTestResult); registerTestRunDescriptor(msg.getTestRunDescriptor()); + + // FIXME: temporary hack before better collection management is found + if (msg.getTestRunDescriptor() == null) { + addResultToCollection("default", treeTestResult.getUuid()); + } } public void addResultPart(ResultPartRequest msg) { diff --git a/runtime/org.argeo.slc.server/src/main/java/org/argeo/slc/services/process/SlcExecutionService.java b/runtime/org.argeo.slc.server/src/main/java/org/argeo/slc/services/process/SlcExecutionService.java index 9e617f743..03afceeaa 100644 --- a/runtime/org.argeo.slc.server/src/main/java/org/argeo/slc/services/process/SlcExecutionService.java +++ b/runtime/org.argeo.slc.server/src/main/java/org/argeo/slc/services/process/SlcExecutionService.java @@ -1,9 +1,13 @@ package org.argeo.slc.services.process; import org.argeo.slc.msg.process.SlcExecutionStatusRequest; +import org.argeo.slc.msg.process.SlcExecutionStepsRequest; import org.argeo.slc.process.SlcExecution; public interface SlcExecutionService { public void newExecution(SlcExecution slcExecutionMsg); + public void updateStatus(SlcExecutionStatusRequest msg); + + public void addSteps(SlcExecutionStepsRequest msg); } diff --git a/runtime/org.argeo.slc.server/src/main/java/org/argeo/slc/web/mvc/process/NewSlcExecutionController.java b/runtime/org.argeo.slc.server/src/main/java/org/argeo/slc/web/mvc/process/NewSlcExecutionController.java index 2e6a45cfe..aaa94a9e1 100644 --- a/runtime/org.argeo.slc.server/src/main/java/org/argeo/slc/web/mvc/process/NewSlcExecutionController.java +++ b/runtime/org.argeo.slc.server/src/main/java/org/argeo/slc/web/mvc/process/NewSlcExecutionController.java @@ -9,6 +9,7 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.argeo.slc.msg.MsgConstants; import org.argeo.slc.process.SlcExecution; +import org.argeo.slc.process.SlcExecutionStep; import org.argeo.slc.runtime.SlcAgent; import org.argeo.slc.runtime.SlcAgentFactory; import org.argeo.slc.services.process.SlcExecutionService; @@ -61,6 +62,9 @@ public class NewSlcExecutionController extends AbstractServiceController { .unmarshal(source); slcExecution.setStatus(SlcExecution.STATUS_SCHEDULED); + slcExecution.getSteps().add( + new SlcExecutionStep(SlcExecutionStep.TYPE_START, + "Process started from the Web UI")); slcExecutionService.newExecution(slcExecution); SlcAgent agent = agentFactory.getAgent(agentId); diff --git a/runtime/org.argeo.slc.specs/src/main/java/org/argeo/slc/execution/ExecutionContext.java b/runtime/org.argeo.slc.specs/src/main/java/org/argeo/slc/execution/ExecutionContext.java index 113755af0..c23fc363c 100644 --- a/runtime/org.argeo.slc.specs/src/main/java/org/argeo/slc/execution/ExecutionContext.java +++ b/runtime/org.argeo.slc.specs/src/main/java/org/argeo/slc/execution/ExecutionContext.java @@ -4,6 +4,10 @@ import java.util.Date; import java.util.Map; public interface ExecutionContext { + public final static String VAR_PROCESS_ID = "slcVar.process.id"; + public final static String VAR_EXECUTION_CONTEXT_ID = "slcVar.executionContext.id"; + public final static String VAR_FLOW_ID = "slcVar.flow.id"; + public final static String VAR_FLOW_NAME = "slcVar.flow.name"; /** * @param name diff --git a/runtime/org.argeo.slc.specs/src/main/java/org/argeo/slc/process/SlcExecution.java b/runtime/org.argeo.slc.specs/src/main/java/org/argeo/slc/process/SlcExecution.java index 0bf52e200..7a81facf6 100644 --- a/runtime/org.argeo.slc.specs/src/main/java/org/argeo/slc/process/SlcExecution.java +++ b/runtime/org.argeo.slc.specs/src/main/java/org/argeo/slc/process/SlcExecution.java @@ -2,6 +2,7 @@ package org.argeo.slc.process; import java.io.Serializable; import java.util.ArrayList; +import java.util.Date; import java.util.List; import java.util.Map; import java.util.TreeMap; @@ -24,6 +25,7 @@ public class SlcExecution implements Serializable { private String status = STATUS_NONE; private Map attributes = new TreeMap(); + /** TODO: Synchronize */ private List steps = new ArrayList(); private List realizedFlows = new ArrayList(); @@ -84,10 +86,12 @@ public class SlcExecution implements Serializable { } public SlcExecutionStep currentStep() { - if (steps.size() > 0) - return steps.get(steps.size() - 1); - else - return null; + synchronized (steps) { + if (steps.size() > 0) + return steps.get(steps.size() - 1); + else + return null; + } } @Override @@ -118,4 +122,25 @@ public class SlcExecution implements Serializable { buf.append(" attributes=").append(attributes); return buf.toString(); } + + public Date getStartDate() { + synchronized (steps) { + if (steps.size() == 0) + return null; + else + return steps.get(0).getBegin(); + } + } + + public Date getEndDate() { + if (!status.equals(STATUS_FINISHED) && !status.equals(STATUS_ERROR)) + return null; + + synchronized (steps) { + if (steps.size() == 0) + return null; + else + return steps.get(steps.size() - 1).getBegin(); + } + } } diff --git a/runtime/org.argeo.slc.specs/src/main/java/org/argeo/slc/process/SlcExecutionStep.java b/runtime/org.argeo.slc.specs/src/main/java/org/argeo/slc/process/SlcExecutionStep.java index 54e363efb..5c54b2c6d 100644 --- a/runtime/org.argeo.slc.specs/src/main/java/org/argeo/slc/process/SlcExecutionStep.java +++ b/runtime/org.argeo.slc.specs/src/main/java/org/argeo/slc/process/SlcExecutionStep.java @@ -2,7 +2,6 @@ package org.argeo.slc.process; import java.io.IOException; import java.io.StringReader; -import java.io.StringWriter; import java.util.ArrayList; import java.util.Date; import java.util.List; @@ -11,21 +10,29 @@ import java.util.UUID; import org.apache.commons.io.IOUtils; public class SlcExecutionStep { + public final static String TYPE_START = "START"; + public final static String TYPE_END = "END"; + public final static String TYPE_PHASE_START = "PHASE_START"; + public final static String TYPE_PHASE_END = "PHASE_END"; public final static String TYPE_LOG = "LOG"; - private String uuid; + private String uuid = UUID.randomUUID().toString(); private String type; - private Date begin; + private Date begin = new Date(); private List logLines = new ArrayList(); /** Empty constructor */ public SlcExecutionStep() { } + /** Creates a step of type LOG. */ public SlcExecutionStep(String log) { - this.type = TYPE_LOG; - this.begin = new Date(); - this.uuid = UUID.randomUUID().toString(); + this(TYPE_LOG, log); + } + + /** Creates a step of the given type. */ + public SlcExecutionStep(String type, String log) { + this.type = type; addLog(log); } @@ -61,13 +68,7 @@ public class SlcExecutionStep { this.logLines = logLines; } - public String logAsString() { - StringWriter writer = new StringWriter(); - String log = writer.toString(); - IOUtils.closeQuietly(writer); - return log; - } - + @SuppressWarnings(value = { "unchecked" }) public void addLog(String log) { if (log == null) return; diff --git a/runtime/org.argeo.slc.support.activemq/src/main/java/org/argeo/slc/jms/JmsSlcExecutionNotifier.java b/runtime/org.argeo.slc.support.activemq/src/main/java/org/argeo/slc/jms/JmsSlcExecutionNotifier.java index 801c6fae3..256e837ab 100644 --- a/runtime/org.argeo.slc.support.activemq/src/main/java/org/argeo/slc/jms/JmsSlcExecutionNotifier.java +++ b/runtime/org.argeo.slc.support.activemq/src/main/java/org/argeo/slc/jms/JmsSlcExecutionNotifier.java @@ -4,31 +4,39 @@ import java.util.List; import javax.jms.Destination; -import org.argeo.slc.SlcException; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; import org.argeo.slc.UnsupportedException; import org.argeo.slc.msg.process.SlcExecutionStatusRequest; +import org.argeo.slc.msg.process.SlcExecutionStepsRequest; import org.argeo.slc.process.SlcExecution; import org.argeo.slc.process.SlcExecutionNotifier; import org.argeo.slc.process.SlcExecutionStep; +import org.springframework.jms.JmsException; import org.springframework.jms.core.JmsTemplate; public class JmsSlcExecutionNotifier implements SlcExecutionNotifier { + private final static Log log = LogFactory + .getLog(JmsSlcExecutionNotifier.class); private JmsTemplate jmsTemplate; private Destination executionEventDestination; - //private Destination updateStatusDestination; + + // private Destination updateStatusDestination; public void updateStatus(SlcExecution slcExecution, String oldStatus, String newStatus) { SlcExecutionStatusRequest req = new SlcExecutionStatusRequest( slcExecution.getUuid(), newStatus); - jmsTemplate.convertAndSend(executionEventDestination, req); + convertAndSend(req); } public void addSteps(SlcExecution slcExecution, List additionalSteps) { - throw new UnsupportedException(); + SlcExecutionStepsRequest req = new SlcExecutionStepsRequest( + slcExecution.getUuid(), additionalSteps); + convertAndSend(req); } public void newExecution(SlcExecution slcExecution) { @@ -43,14 +51,19 @@ public class JmsSlcExecutionNotifier implements SlcExecutionNotifier { this.jmsTemplate = jmsTemplate; } - public void setExecutionEventDestination(Destination executionEventDestination) { + public void setExecutionEventDestination( + Destination executionEventDestination) { this.executionEventDestination = executionEventDestination; } - - -// public void setUpdateStatusDestination(Destination updateStatusDestination) { -// this.updateStatusDestination = updateStatusDestination; -// } - + protected void convertAndSend(Object req) { + try { + jmsTemplate.convertAndSend(executionEventDestination, req); + } catch (JmsException e) { + log.warn("Send request " + req.getClass() + " to server: " + + e.getMessage()); + if (log.isTraceEnabled()) + log.debug("Original error.", e); + } + } } diff --git a/runtime/org.argeo.slc.support.activemq/src/main/java/org/argeo/slc/jms/JmsTreeTestResultListener.java b/runtime/org.argeo.slc.support.activemq/src/main/java/org/argeo/slc/jms/JmsTreeTestResultListener.java index 7da976a4d..7807b4219 100644 --- a/runtime/org.argeo.slc.support.activemq/src/main/java/org/argeo/slc/jms/JmsTreeTestResultListener.java +++ b/runtime/org.argeo.slc.support.activemq/src/main/java/org/argeo/slc/jms/JmsTreeTestResultListener.java @@ -13,8 +13,8 @@ import org.argeo.slc.msg.test.tree.AddTreeTestResultAttachmentRequest; import org.argeo.slc.msg.test.tree.CloseTreeTestResultRequest; import org.argeo.slc.msg.test.tree.CreateTreeTestResultRequest; import org.argeo.slc.msg.test.tree.ResultPartRequest; -import org.argeo.slc.test.TestResultListener; import org.argeo.slc.test.TestResultPart; +import org.springframework.jms.JmsException; import org.springframework.jms.core.JmsTemplate; public class JmsTreeTestResultListener implements TreeTestResultListener { @@ -25,10 +25,6 @@ public class JmsTreeTestResultListener implements TreeTestResultListener { private Destination executionEventDestination; - // private Destination createDestination; - // private Destination addResultPartDestination; - // private Destination closeDestination; - public void resultPartAdded(TreeTestResult testResult, TestResultPart testResultPart) { if (onlyOnClose) @@ -55,6 +51,11 @@ public class JmsTreeTestResultListener implements TreeTestResultListener { jmsTemplate.convertAndSend(executionEventDestination, req); } + } catch (JmsException e) { + log.warn("Could not notify result part to server: " + + e.getMessage()); + if (log.isTraceEnabled()) + log.debug("Original error.", e); } catch (Exception e) { throw new SlcException("Could not notify to JMS", e); } @@ -82,6 +83,11 @@ public class JmsTreeTestResultListener implements TreeTestResultListener { jmsTemplate.convertAndSend(executionEventDestination, req); } + } catch (JmsException e) { + log.warn("Could not notify result close to server: " + + e.getMessage()); + if (log.isTraceEnabled()) + log.debug("Original error.", e); } catch (Exception e) { throw new SlcException("Could not notify to JMS", e); } @@ -94,6 +100,12 @@ public class JmsTreeTestResultListener implements TreeTestResultListener { req.setAttachment((SimpleAttachment) attachment); jmsTemplate.convertAndSend(executionEventDestination, req); + } catch (JmsException e) { + log + .warn("Could not notify attachment to server: " + + e.getMessage()); + if (log.isTraceEnabled()) + log.debug("Original error.", e); } catch (Exception e) { throw new SlcException("Could not notify to JMS", e); } diff --git a/runtime/org.argeo.slc.support.castor/src/main/resources/org/argeo/slc/castor/msg.xml b/runtime/org.argeo.slc.support.castor/src/main/resources/org/argeo/slc/castor/msg.xml index b295a610f..b5246c47c 100644 --- a/runtime/org.argeo.slc.support.castor/src/main/resources/org/argeo/slc/castor/msg.xml +++ b/runtime/org.argeo.slc.support.castor/src/main/resources/org/argeo/slc/castor/msg.xml @@ -145,7 +145,7 @@ - diff --git a/runtime/org.argeo.slc.support.hibernate/src/main/resources/org/argeo/slc/hibernate/process/SlcExecution.hbm.xml b/runtime/org.argeo.slc.support.hibernate/src/main/resources/org/argeo/slc/hibernate/process/SlcExecution.hbm.xml index edc0f735a..6eb4c08c0 100644 --- a/runtime/org.argeo.slc.support.hibernate/src/main/resources/org/argeo/slc/hibernate/process/SlcExecution.hbm.xml +++ b/runtime/org.argeo.slc.support.hibernate/src/main/resources/org/argeo/slc/hibernate/process/SlcExecution.hbm.xml @@ -12,12 +12,12 @@ - + - + , ResourceLoaderAware { - private final static Log log = LogFactory - .getLog(DefaultExecutionFlow.class); - private final ExecutionSpec executionSpec; private String name = null; private Map parameters = new HashMap(); diff --git a/runtime/org.argeo.slc.support.simple/src/main/java/org/argeo/slc/core/execution/DefaultModulesManager.java b/runtime/org.argeo.slc.support.simple/src/main/java/org/argeo/slc/core/execution/DefaultModulesManager.java index 05a0e8dae..b843c4ff0 100644 --- a/runtime/org.argeo.slc.support.simple/src/main/java/org/argeo/slc/core/execution/DefaultModulesManager.java +++ b/runtime/org.argeo.slc.support.simple/src/main/java/org/argeo/slc/core/execution/DefaultModulesManager.java @@ -14,7 +14,7 @@ import org.argeo.slc.execution.ExecutionModulesManager; import org.argeo.slc.process.RealizedFlow; import org.argeo.slc.process.SlcExecution; import org.argeo.slc.process.SlcExecutionNotifier; -import org.springframework.util.Assert; +import org.argeo.slc.process.SlcExecutionStep; public class DefaultModulesManager implements ExecutionModulesManager { private final static Log log = LogFactory @@ -22,6 +22,7 @@ public class DefaultModulesManager implements ExecutionModulesManager { private List executionModules = new ArrayList(); private List slcExecutionNotifiers = new ArrayList(); + private ThreadGroup processesThreadGroup = new ThreadGroup("Processes"); protected ExecutionModule getExecutionModule(String moduleName, String version) { @@ -39,8 +40,9 @@ public class DefaultModulesManager implements ExecutionModulesManager { String moduleName, String version) { ExecutionModule module = getExecutionModule(moduleName, version); - if(module==null) - throw new SlcException("Module "+moduleName+" ("+version+") not found"); + if (module == null) + throw new SlcException("Module " + moduleName + " (" + version + + ") not found"); return module.getDescriptor(); } @@ -54,7 +56,7 @@ public class DefaultModulesManager implements ExecutionModulesManager { } public void process(SlcExecution slcExecution) { - new ProcessThread(slcExecution).start(); + new ProcessThread(processesThreadGroup, slcExecution).start(); } protected void dispatchUpdateStatus(SlcExecution slcExecution, @@ -65,22 +67,39 @@ public class DefaultModulesManager implements ExecutionModulesManager { } } + protected synchronized void dispatchAddStep(SlcExecution slcExecution, + SlcExecutionStep step) { + slcExecution.getSteps().add(step); + List steps = new ArrayList(); + steps.add(step); + for (Iterator it = slcExecutionNotifiers + .iterator(); it.hasNext();) { + it.next().addSteps(slcExecution, steps); + } + } + public void setSlcExecutionNotifiers( List slcExecutionNotifiers) { this.slcExecutionNotifiers = slcExecutionNotifiers; } + /** Thread of the SLC Process, starting the sub executions. */ private class ProcessThread extends Thread { - private final SlcExecution slcExecution; + private final SlcExecution slcProcess; + private final ThreadGroup processThreadGroup; private final List flowsToProcess = new ArrayList(); - public ProcessThread(SlcExecution slcExecution) { - this.slcExecution = slcExecution; + public ProcessThread(ThreadGroup processesThreadGroup, + SlcExecution slcExecution) { + super(processesThreadGroup, "SLC Process #" + + slcExecution.getUuid()); + this.slcProcess = slcExecution; + processThreadGroup = new ThreadGroup("SLC Process #" + + slcExecution.getUuid() + " thread group"); } public void run() { - log.info("\n##\n## Process SLC Execution " + slcExecution - + "\n##\n"); + log.info("\n##\n## Process SLC Execution " + slcProcess + "\n##\n"); // FIXME: hack to let the SlcExecution be registered on server try { @@ -89,11 +108,11 @@ public class DefaultModulesManager implements ExecutionModulesManager { // silent } - slcExecution.setStatus(SlcExecution.STATUS_RUNNING); - dispatchUpdateStatus(slcExecution, SlcExecution.STATUS_SCHEDULED, + slcProcess.setStatus(SlcExecution.STATUS_RUNNING); + dispatchUpdateStatus(slcProcess, SlcExecution.STATUS_SCHEDULED, SlcExecution.STATUS_RUNNING); - flowsToProcess.addAll(slcExecution.getRealizedFlows()); + flowsToProcess.addAll(slcProcess.getRealizedFlows()); while (flowsToProcess.size() > 0) { RealizedFlow flow = flowsToProcess.remove(0); @@ -118,25 +137,25 @@ public class DefaultModulesManager implements ExecutionModulesManager { } } - slcExecution.setStatus(SlcExecution.STATUS_RUNNING); - dispatchUpdateStatus(slcExecution, SlcExecution.STATUS_RUNNING, + slcProcess.setStatus(SlcExecution.STATUS_FINISHED); + dispatchUpdateStatus(slcProcess, SlcExecution.STATUS_RUNNING, SlcExecution.STATUS_FINISHED); - /* - * for (RealizedFlow flow : slcExecution.getRealizedFlows()) { - * ExecutionModule module = getExecutionModule(flow.getModuleName(), - * flow.getModuleVersion()); if (module != null) { ExecutionThread - * thread = new ExecutionThread(flow .getFlowDescriptor(), module); - * thread.start(); } else { throw new - * SlcException("ExecutionModule " + flow.getModuleName() + - * ", version " + flow.getModuleVersion() + " not found."); } } - */ } public synchronized void flowCompleted() { notifyAll(); } + + public SlcExecution getSlcProcess() { + return slcProcess; + } + + public ThreadGroup getProcessThreadGroup() { + return processThreadGroup; + } } + /** Thread of a single execution */ private class ExecutionThread extends Thread { private final ExecutionFlowDescriptor executionFlowDescriptor; private final ExecutionModule executionModule; @@ -145,21 +164,32 @@ public class DefaultModulesManager implements ExecutionModulesManager { public ExecutionThread(ProcessThread processThread, ExecutionFlowDescriptor executionFlowDescriptor, ExecutionModule executionModule) { - super("SLC Execution #" /* + executionContext.getUuid() */); + super(processThread.getProcessThreadGroup(), "Flow " + + executionFlowDescriptor.getName()); this.executionFlowDescriptor = executionFlowDescriptor; this.executionModule = executionModule; this.processThread = processThread; } public void run() { + dispatchAddStep(processThread.getSlcProcess(), + new SlcExecutionStep(SlcExecutionStep.TYPE_PHASE_START, + "Flow " + executionFlowDescriptor.getName())); + try { executionModule.execute(executionFlowDescriptor); } catch (Exception e) { // TODO: re-throw exception ? - log.error("Execution "/* + executionContext.getUuid() */ - + " failed.", e); + String msg = "Execution of flow " + + executionFlowDescriptor.getName() + " failed."; + log.error(msg, e); + dispatchAddStep(processThread.getSlcProcess(), + new SlcExecutionStep(msg + " " + e.getMessage())); } finally { processThread.flowCompleted(); + dispatchAddStep(processThread.getSlcProcess(), + new SlcExecutionStep(SlcExecutionStep.TYPE_PHASE_END, + "Flow " + executionFlowDescriptor.getName())); } } } diff --git a/runtime/org.argeo.slc.support.simple/src/main/java/org/argeo/slc/core/execution/FileExecutionResources.java b/runtime/org.argeo.slc.support.simple/src/main/java/org/argeo/slc/core/execution/FileExecutionResources.java index e032e6a0c..361cede76 100644 --- a/runtime/org.argeo.slc.support.simple/src/main/java/org/argeo/slc/core/execution/FileExecutionResources.java +++ b/runtime/org.argeo.slc.support.simple/src/main/java/org/argeo/slc/core/execution/FileExecutionResources.java @@ -39,7 +39,6 @@ public class FileExecutionResources implements ExecutionResources { String osgiInstanceArea = System.getProperty("osgi.instance.area"); String osgiInstanceAreaDefault = System .getProperty("osgi.instance.area.default"); - String tempDir = System.getProperty("java.io.tmpdir"); if (osgiInstanceArea != null) { // within OSGi with -data specified @@ -118,9 +117,9 @@ public class FileExecutionResources implements ExecutionResources { } public File getFile(String relativePath) { - Assert.notNull(executionContext, "execution context is null"); if (withExecutionSubdirectory) { + Assert.notNull(executionContext, "execution context is null"); String path = baseDir.getPath() + File.separator + sdf().format(executionContext.getCreationDate()) + executionContext.getUuid(); @@ -167,6 +166,7 @@ public class FileExecutionResources implements ExecutionResources { return prefixDatePattern; } + /** Default is true. */ public void setWithExecutionSubdirectory(Boolean withExecutionSubdirectory) { this.withExecutionSubdirectory = withExecutionSubdirectory; } diff --git a/runtime/org.argeo.slc.support.simple/src/main/java/org/argeo/slc/core/execution/MapExecutionContext.java b/runtime/org.argeo.slc.support.simple/src/main/java/org/argeo/slc/core/execution/MapExecutionContext.java index 9e6c2b5bd..2dc9b867c 100644 --- a/runtime/org.argeo.slc.support.simple/src/main/java/org/argeo/slc/core/execution/MapExecutionContext.java +++ b/runtime/org.argeo.slc.support.simple/src/main/java/org/argeo/slc/core/execution/MapExecutionContext.java @@ -14,6 +14,7 @@ import org.argeo.slc.execution.ExecutionFlow; import org.argeo.slc.execution.ExecutionSpecAttribute; public class MapExecutionContext implements ExecutionContext { + private final static Log log = LogFactory.getLog(MapExecutionContext.class); private final Stack stack = new Stack(); @@ -27,6 +28,7 @@ public class MapExecutionContext implements ExecutionContext { public MapExecutionContext() { uuid = UUID.randomUUID().toString(); + variables.put(VAR_EXECUTION_CONTEXT_ID, uuid); } public void addVariables( @@ -37,6 +39,8 @@ public class MapExecutionContext implements ExecutionContext { public void enterFlow(ExecutionFlow executionFlow) { ExecutionFlowRuntime runtime = new ExecutionFlowRuntime(executionFlow); stack.push(runtime); + variables.put(VAR_FLOW_ID, runtime.getUuid()); + variables.put(VAR_FLOW_NAME, runtime.getExecutionFlow().getName()); if (log.isDebugEnabled()) log.debug(depthSpaces(stack.size()) + "=> " + executionFlow + " #" diff --git a/runtime/org.argeo.slc.support.simple/src/main/java/org/argeo/slc/core/execution/tasks/SystemCall.java b/runtime/org.argeo.slc.support.simple/src/main/java/org/argeo/slc/core/execution/tasks/SystemCall.java index 143bded2a..0ea1f7bee 100644 --- a/runtime/org.argeo.slc.support.simple/src/main/java/org/argeo/slc/core/execution/tasks/SystemCall.java +++ b/runtime/org.argeo.slc.support.simple/src/main/java/org/argeo/slc/core/execution/tasks/SystemCall.java @@ -1,6 +1,9 @@ package org.argeo.slc.core.execution.tasks; import java.io.File; +import java.io.FileWriter; +import java.io.IOException; +import java.io.Writer; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -14,13 +17,22 @@ import org.apache.commons.exec.Executor; import org.apache.commons.exec.LogOutputStream; import org.apache.commons.exec.PumpStreamHandler; import org.apache.commons.exec.ShutdownHookProcessDestroyer; +import org.apache.commons.io.IOUtils; import org.apache.commons.lang.NotImplementedException; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.argeo.slc.SlcException; +import org.argeo.slc.core.structure.tree.TreeSPath; +import org.argeo.slc.core.structure.tree.TreeSRelatedHelper; +import org.argeo.slc.core.test.SimpleResultPart; +import org.argeo.slc.structure.StructureAware; +import org.argeo.slc.test.TestResult; +import org.argeo.slc.test.TestStatus; +import org.springframework.core.io.Resource; /** Execute and OS system call. */ -public class SystemCall implements Runnable { +public class SystemCall extends TreeSRelatedHelper implements Runnable, + StructureAware { private final Log log = LogFactory.getLog(getClass()); private String execDir; @@ -33,13 +45,34 @@ public class SystemCall implements Runnable { private String stdErrLogLevel = "ERROR"; private String stdOutLogLevel = "INFO"; + private Resource stdOutFile = null; + private Resource stdErrFile = null; + private Map> osCommands = new HashMap>(); private Map osCmds = new HashMap(); private Map environmentVariables = new HashMap(); private Long watchdogTimeout = 24 * 60 * 60 * 1000l; + private TestResult testResult; + public void run() { + // Log writers + final Writer stdOutWriter; + final Writer stdErrWriter; + if (stdOutFile != null) { + stdOutWriter = createWriter(stdOutFile); + } else + stdOutWriter = null; + if (stdErrFile != null) { + stdErrWriter = createWriter(stdErrFile); + } else { + if (stdOutFile != null) { + stdErrWriter = createWriter(stdOutFile); + } else + stdErrWriter = null; + } + try { if (log.isTraceEnabled()) { log.debug("os.name=" + System.getProperty("os.name")); @@ -76,14 +109,19 @@ public class SystemCall implements Runnable { Executor executor = new DefaultExecutor(); executor.setWatchdog(new ExecuteWatchdog(watchdogTimeout)); + PumpStreamHandler pumpStreamHandler = new PumpStreamHandler( new LogOutputStream() { protected void processLine(String line, int level) { log(stdOutLogLevel, line); + if (stdOutWriter != null) + appendLineToFile(stdOutWriter, line); } }, new LogOutputStream() { protected void processLine(String line, int level) { log(stdErrLogLevel, line); + if (stdErrWriter != null) + appendLineToFile(stdErrWriter, line); } }, null); executor.setStreamHandler(pumpStreamHandler); @@ -129,11 +167,24 @@ public class SystemCall implements Runnable { if (log.isDebugEnabled()) log.debug("Process " + commandLine + " properly completed."); + if (testResult != null) { + forwardPath(testResult, null); + testResult.addResultPart(new SimpleResultPart( + TestStatus.PASSED, "Process " + commandLine + + " properly completed.")); + } } public void onProcessFailed(ExecuteException e) { - throw new SlcException("Process " + commandLine - + " failed.", e); + if (testResult != null) { + forwardPath(testResult, null); + testResult.addResultPart(new SimpleResultPart( + TestStatus.ERROR, "Process " + commandLine + + " failed.", e)); + } else { + throw new SlcException("Process " + commandLine + + " failed.", e); + } } }; @@ -150,6 +201,9 @@ public class SystemCall implements Runnable { executeResultHandler); } catch (Exception e) { throw new SlcException("Could not execute command " + cmd, e); + } finally { + IOUtils.closeQuietly(stdOutWriter); + IOUtils.closeQuietly(stdErrWriter); } } @@ -180,6 +234,26 @@ public class SystemCall implements Runnable { throw new SlcException("Unknown log level " + logLevel); } + protected void appendLineToFile(Writer writer, String line) { + try { + writer.append(line).append('\n'); + } catch (IOException e) { + log.error("Cannot write to log file", e); + } + } + + protected Writer createWriter(Resource target) { + FileWriter writer = null; + try { + File file = target.getFile(); + writer = new FileWriter(file, true); + } catch (IOException e) { + log.error("Cannot create log file " + target, e); + IOUtils.closeQuietly(writer); + } + return writer; + } + public void setCmd(String command) { this.cmd = command; } @@ -220,4 +294,16 @@ public class SystemCall implements Runnable { this.watchdogTimeout = watchdogTimeout; } + public void setStdOutFile(Resource stdOutFile) { + this.stdOutFile = stdOutFile; + } + + public void setStdErrFile(Resource stdErrFile) { + this.stdErrFile = stdErrFile; + } + + public void setTestResult(TestResult testResult) { + this.testResult = testResult; + } + } diff --git a/runtime/org.argeo.slc.support.simple/src/main/java/org/argeo/slc/core/structure/tree/TreeSRelatedHelper.java b/runtime/org.argeo.slc.support.simple/src/main/java/org/argeo/slc/core/structure/tree/TreeSRelatedHelper.java index 8dc00784e..b0cc87bf9 100644 --- a/runtime/org.argeo.slc.support.simple/src/main/java/org/argeo/slc/core/structure/tree/TreeSRelatedHelper.java +++ b/runtime/org.argeo.slc.support.simple/src/main/java/org/argeo/slc/core/structure/tree/TreeSRelatedHelper.java @@ -1,16 +1,22 @@ package org.argeo.slc.core.structure.tree; import org.argeo.slc.core.structure.SimpleSElement; +import org.argeo.slc.structure.StructureAware; import org.argeo.slc.structure.StructureElement; import org.argeo.slc.structure.StructureRegistry; /** - * Provides default implementations of some methods of TreeSRelated. + * Provides default implementations of some methods of TreeSRelated + * . */ public abstract class TreeSRelatedHelper implements TreeSRelated { private TreeSPath basePath; private StructureRegistry registry; + // private ThreadLocal basePath = new ThreadLocal(); + // private ThreadLocal> registry = new + // ThreadLocal>(); + public TreeSPath getBasePath() { return basePath; } @@ -21,7 +27,7 @@ public abstract class TreeSRelatedHelper implements TreeSRelated { public void notifyCurrentPath(StructureRegistry registry, TreeSPath path) { - basePath = path; + this.basePath = path; this.registry = registry; } @@ -29,4 +35,24 @@ public abstract class TreeSRelatedHelper implements TreeSRelated { return new SimpleSElement(key); } + /** + * Checks wether the object is {@link StructureAware} and forward path and + * registry. null safe for both arguments. + */ + @SuppressWarnings(value = { "unchecked" }) + protected void forwardPath(Object obj, String childName) { + if (obj == null) + return; + + if (obj instanceof StructureAware && basePath != null) { + TreeSPath path; + if (childName != null) + path = basePath.createChild(childName); + else + path = basePath; + + ((StructureAware) obj).notifyCurrentPath(registry, path); + } + } + } diff --git a/runtime/org.argeo.slc.support.simple/src/main/java/org/argeo/slc/msg/process/SlcExecutionStepsRequest.java b/runtime/org.argeo.slc.support.simple/src/main/java/org/argeo/slc/msg/process/SlcExecutionStepsRequest.java index c7cdc604d..56feca86c 100644 --- a/runtime/org.argeo.slc.support.simple/src/main/java/org/argeo/slc/msg/process/SlcExecutionStepsRequest.java +++ b/runtime/org.argeo.slc.support.simple/src/main/java/org/argeo/slc/msg/process/SlcExecutionStepsRequest.java @@ -1,5 +1,6 @@ package org.argeo.slc.msg.process; +import java.util.ArrayList; import java.util.List; import java.util.Vector; @@ -7,7 +8,7 @@ import org.argeo.slc.process.SlcExecutionStep; public class SlcExecutionStepsRequest { private String slcExecutionUuid; - private List steps = new Vector(); + private List steps = new ArrayList(); public SlcExecutionStepsRequest() { diff --git a/runtime/org.argeo.slc.support.simple/src/main/java/org/argeo/slc/unit/process/SlcExecutionTestUtils.java b/runtime/org.argeo.slc.support.simple/src/main/java/org/argeo/slc/unit/process/SlcExecutionTestUtils.java index bbea1bb25..8bf941601 100644 --- a/runtime/org.argeo.slc.support.simple/src/main/java/org/argeo/slc/unit/process/SlcExecutionTestUtils.java +++ b/runtime/org.argeo.slc.support.simple/src/main/java/org/argeo/slc/unit/process/SlcExecutionTestUtils.java @@ -53,7 +53,6 @@ public abstract class SlcExecutionTestUtils { assertNotNull(reached); assertEquals(expected.getUuid(), reached.getUuid()); assertEquals(expected.getType(), reached.getType()); - assertEquals(expected.logAsString(), reached.logAsString()); assertDateSec(expected.getBegin(), reached.getBegin()); } diff --git a/server/org.argeo.slc.siteserver/bundles/org.argeo.slc.server.main/META-INF/MANIFEST.MF b/server/org.argeo.slc.siteserver/bundles/org.argeo.slc.server.main/META-INF/MANIFEST.MF new file mode 100644 index 000000000..d3ec3e14e --- /dev/null +++ b/server/org.argeo.slc.siteserver/bundles/org.argeo.slc.server.main/META-INF/MANIFEST.MF @@ -0,0 +1,7 @@ +Manifest-Version: 1.0 +Bundle-SymbolicName: org.argeo.slc.server.main +Bundle-Version: 0.11.4.SNAPSHOT +Bundle-Name: SLC Server Main +Require-Bundle: org.argeo.slc.server, + org.argeo.slc.specs, + org.argeo.slc.support.simple diff --git a/server/org.argeo.slc.siteserver/bundles/org.argeo.slc.server.main/META-INF/spring/main.xml b/server/org.argeo.slc.siteserver/bundles/org.argeo.slc.server.main/META-INF/spring/main.xml new file mode 100644 index 000000000..6c4b88f91 --- /dev/null +++ b/server/org.argeo.slc.siteserver/bundles/org.argeo.slc.server.main/META-INF/spring/main.xml @@ -0,0 +1,22 @@ + + + + + + + + + + + \ No newline at end of file