]> git.argeo.org Git - gpl/argeo-slc.git/commitdiff
Improve process management
authorMathieu Baudier <mbaudier@argeo.org>
Wed, 20 Apr 2011 07:57:21 +0000 (07:57 +0000)
committerMathieu Baudier <mbaudier@argeo.org>
Wed, 20 Apr 2011 07:57:21 +0000 (07:57 +0000)
ASSIGNED - bug 17: Generalize agent management and registration beyond JMS
https://bugzilla.argeo.org/show_bug.cgi?id=17

git-svn-id: https://svn.argeo.org/slc/trunk@4462 4cfe0d0a-d680-48aa-b62c-e0a02a3f76cc

12 files changed:
demo/slc_demo_rcp.properties
eclipse/plugins/org.argeo.slc.client.ui/icons/kill.png [new file with mode: 0644]
eclipse/plugins/org.argeo.slc.client.ui/icons/relaunch.gif [new file with mode: 0644]
eclipse/plugins/org.argeo.slc.client.ui/src/main/java/org/argeo/slc/client/ui/SlcImages.java
eclipse/plugins/org.argeo.slc.client.ui/src/main/java/org/argeo/slc/client/ui/editors/ProcessBuilderPage.java
eclipse/plugins/org.argeo.slc.client.ui/src/main/java/org/argeo/slc/client/ui/editors/ProcessEditor.java
eclipse/plugins/org.argeo.slc.client.ui/src/main/java/org/argeo/slc/client/ui/editors/ProcessEditorInput.java
eclipse/plugins/org.argeo.slc.client.ui/src/main/java/org/argeo/slc/client/ui/views/JcrProcessListView.java
runtime/org.argeo.slc.specs/src/main/java/org/argeo/slc/execution/ExecutionProcess.java
runtime/org.argeo.slc.specs/src/main/java/org/argeo/slc/process/SlcExecution.java
runtime/org.argeo.slc.support.jcr/src/main/java/org/argeo/slc/jcr/SlcJcrUtils.java
runtime/org.argeo.slc.support.jcr/src/main/java/org/argeo/slc/jcr/execution/JcrExecutionProcess.java

index f90dd780f53cea09bb94655e5150b079a15cb4ac..2e380ad923ababf2140e8977042b421feaa73729 100644 (file)
@@ -1,7 +1,7 @@
 argeo.osgi.start=\
 org.springframework.osgi.extender,\
 org.argeo.slc.client.rcp,\
-org.argeo.slc.server.jcr,\
+org.argeo.slc.agent.jcr,\
 org.argeo.slc.demo.ant,\
 org.argeo.slc.demo.basic,\
 
diff --git a/eclipse/plugins/org.argeo.slc.client.ui/icons/kill.png b/eclipse/plugins/org.argeo.slc.client.ui/icons/kill.png
new file mode 100644 (file)
index 0000000..cfbf9d1
Binary files /dev/null and b/eclipse/plugins/org.argeo.slc.client.ui/icons/kill.png differ
diff --git a/eclipse/plugins/org.argeo.slc.client.ui/icons/relaunch.gif b/eclipse/plugins/org.argeo.slc.client.ui/icons/relaunch.gif
new file mode 100644 (file)
index 0000000..8f943a8
Binary files /dev/null and b/eclipse/plugins/org.argeo.slc.client.ui/icons/relaunch.gif differ
index 1bc7ff512f243525f7a6883ea96d8c166f9b190d..d9fe3cddb104a267bc82aa37960b471ed89b1477 100644 (file)
@@ -13,6 +13,7 @@ public class SlcImages {
        public final static Image PASSED = img("icons/passed.gif");
        public final static Image ERROR = img("icons/error.gif");
        public final static Image LAUNCH = img("icons/launch.gif");
+       public final static Image RELAUNCH = img("icons/relaunch.gif");
        public final static Image REMOVE_ONE = img("icons/remove_one.gif");
        public final static Image REMOVE_ALL = img("icons/removeAll.png");
 }
index 6a217808924c2969c3ebc11bd34a9e399eb0d080..9154714d82ef5f4776e6d4e7b8a21b030b56e04a 100644 (file)
@@ -3,11 +3,13 @@ package org.argeo.slc.client.ui.editors;
 import java.util.ArrayList;
 import java.util.Iterator;
 import java.util.List;
+import java.util.UUID;
 
 import javax.jcr.Node;
 import javax.jcr.NodeIterator;
 import javax.jcr.Property;
 import javax.jcr.RepositoryException;
+import javax.jcr.Session;
 import javax.jcr.nodetype.NodeType;
 import javax.jcr.observation.Event;
 import javax.jcr.observation.EventIterator;
@@ -15,6 +17,7 @@ import javax.jcr.observation.EventListener;
 import javax.jcr.observation.ObservationManager;
 
 import org.argeo.ArgeoException;
+import org.argeo.eclipse.ui.jcr.AsyncUiEventListener;
 import org.argeo.jcr.JcrUtils;
 import org.argeo.slc.SlcException;
 import org.argeo.slc.client.ui.SlcImages;
@@ -44,6 +47,7 @@ import org.eclipse.swt.graphics.Image;
 import org.eclipse.swt.layout.FillLayout;
 import org.eclipse.swt.layout.GridData;
 import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.layout.RowData;
 import org.eclipse.swt.layout.RowLayout;
 import org.eclipse.swt.widgets.Button;
 import org.eclipse.swt.widgets.Composite;
@@ -57,20 +61,23 @@ import org.eclipse.ui.forms.widgets.ScrolledForm;
 
 public class ProcessBuilderPage extends FormPage implements SlcNames, SlcTypes {
        public final static String ID = "processBuilderPage";
-       //private final static Log log = LogFactory.getLog(ProcessBuilderPage.class);
+       // private final static Log log =
+       // LogFactory.getLog(ProcessBuilderPage.class);
 
        private Node processNode;
 
        private TreeViewer flowsViewer;
-       private Label status;
+       private Label statusLabel;
+       private Button run;
+       private Button remove;
+       private Button clear;
 
        private AbstractFormPart formPart;
-       private StatusObserver statusObserver;
+       private EventListener statusObserver;
 
        public ProcessBuilderPage(ProcessEditor editor, Node processNode) {
                super(editor, ID, "Definition");
                this.processNode = processNode;
-
        }
 
        @Override
@@ -89,11 +96,13 @@ public class ProcessBuilderPage extends FormPage implements SlcNames, SlcTypes {
 
                        };
                        getManagedForm().addPart(formPart);
-                       if (getProcessStatus().equals(ExecutionProcess.UNINITIALIZED))
-                               formPart.markDirty();
 
                        // observation
-                       statusObserver = new StatusObserver();
+                       statusObserver = new AsyncUiEventListener() {
+                               protected void onEventInUiThread(EventIterator events) {
+                                       statusChanged();
+                               }
+                       };
                        ObservationManager observationManager = processNode.getSession()
                                        .getWorkspace().getObservationManager();
                        observationManager.addEventListener(statusObserver,
@@ -112,12 +121,16 @@ public class ProcessBuilderPage extends FormPage implements SlcNames, SlcTypes {
                controls.setLayout(new RowLayout());
                controls.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
 
-               Button run = tk.createButton(controls, null, SWT.PUSH);
+               run = tk.createButton(controls, null, SWT.PUSH);
                run.setToolTipText("Run");
                run.setImage(SlcImages.LAUNCH);
                run.addSelectionListener(new SelectionListener() {
                        public void widgetSelected(SelectionEvent e) {
-                               ((ProcessEditor) getEditor()).process();
+                               if (isFinished(getProcessStatus())) {
+                                       relaunch();
+                               } else {
+                                       ((ProcessEditor) getEditor()).process();
+                               }
                        }
 
                        public void widgetDefaultSelected(SelectionEvent e) {
@@ -125,7 +138,7 @@ public class ProcessBuilderPage extends FormPage implements SlcNames, SlcTypes {
                        }
                });
 
-               Button remove = tk.createButton(controls, null, SWT.PUSH);
+               remove = tk.createButton(controls, null, SWT.PUSH);
                remove.setImage(SlcImages.REMOVE_ONE);
                remove.setToolTipText("Remove selected flows");
                remove.addSelectionListener(new SelectionListener() {
@@ -138,7 +151,7 @@ public class ProcessBuilderPage extends FormPage implements SlcNames, SlcTypes {
                        }
                });
 
-               Button clear = tk.createButton(controls, null, SWT.PUSH);
+               clear = tk.createButton(controls, null, SWT.PUSH);
                clear.setImage(SlcImages.REMOVE_ALL);
                clear.setToolTipText("Clear all flows");
                clear.addSelectionListener(new SelectionListener() {
@@ -151,7 +164,53 @@ public class ProcessBuilderPage extends FormPage implements SlcNames, SlcTypes {
                        }
                });
 
-               status = tk.createLabel(controls, getProcessStatus());
+               Composite statusComposite = tk.createComposite(controls);
+               RowData rowData = new RowData();
+               rowData.width = 100;
+               rowData.height = 16;
+               statusComposite.setLayoutData(rowData);
+               statusComposite.setLayout(new FillLayout());
+               statusLabel = tk.createLabel(statusComposite, getProcessStatus());
+
+               // make sure all controls are in line with status
+               statusChanged();
+       }
+
+       protected void relaunch() {
+               try {
+                       Node duplicatedNode = duplicateProcess();
+                       PlatformUI
+                                       .getWorkbench()
+                                       .getActiveWorkbenchWindow()
+                                       .getActivePage()
+                                       .openEditor(
+                                                       new ProcessEditorInput(duplicatedNode.getPath()),
+                                                       ProcessEditor.ID);
+                       getEditor().close(false);
+               } catch (Exception e1) {
+                       throw new SlcException("Cannot relaunch " + processNode, e1);
+               }
+       }
+
+       protected Node duplicateProcess() {
+               try {
+                       Session session = processNode.getSession();
+                       String uuid = UUID.randomUUID().toString();
+                       String destPath = SlcJcrUtils.createExecutionProcessPath(uuid);
+                       Node newNode = JcrUtils.mkdirs(session, destPath, SLC_PROCESS);
+                       JcrUtils.copy(processNode, newNode);
+//                     session.getWorkspace().copy(processNode.getPath(), destPath);
+//                     Node newNode = session.getNode(destPath);
+                       // make sure that we kept the mixins
+//                     newNode.addMixin(NodeType.MIX_CREATED);
+//                     newNode.addMixin(NodeType.MIX_LAST_MODIFIED);
+                       newNode.setProperty(SLC_UUID, uuid);
+                       newNode.setProperty(SLC_STATUS, ExecutionProcess.INITIALIZED);
+                       session.save();
+                       return newNode;
+               } catch (RepositoryException e) {
+                       throw new SlcException("Cannot duplicate process", e);
+               }
        }
 
        protected String getProcessStatus() {
@@ -163,6 +222,33 @@ public class ProcessBuilderPage extends FormPage implements SlcNames, SlcTypes {
                }
        }
 
+       protected void statusChanged() {
+               String status = getProcessStatus();
+               statusLabel.setText(status);
+               Boolean isEditable = isEditable(status);
+               run.setEnabled(isEditable);
+               remove.setEnabled(isEditable);
+               clear.setEnabled(isEditable);
+               // flowsViewer.getTree().setEnabled(isEditable);
+               if (status.equals(ExecutionProcess.COMPLETED)
+                               || status.equals(ExecutionProcess.ERROR)) {
+                       run.setEnabled(true);
+                       run.setImage(SlcImages.RELAUNCH);
+                       run.setToolTipText("Relaunch");
+               }
+       }
+
+       /** Optimization so that we don't call the node each time */
+       protected Boolean isEditable(String status) {
+               return status.equals(ExecutionProcess.NEW)
+                               || status.equals(ExecutionProcess.INITIALIZED);
+       }
+
+       protected Boolean isFinished(String status) {
+               return status.equals(ExecutionProcess.COMPLETED)
+                               || status.equals(ExecutionProcess.ERROR);
+       }
+
        protected void createBuilder(Composite parent) {
                FormToolkit tk = getManagedForm().getToolkit();
                SashForm sashForm = new SashForm(parent, SWT.HORIZONTAL);
@@ -247,14 +333,11 @@ public class ProcessBuilderPage extends FormPage implements SlcNames, SlcTypes {
        }
 
        public void commit(Boolean onSave) {
+               if (onSave)
+                       statusLabel.setText(getProcessStatus());
                formPart.commit(onSave);
        }
 
-       @Override
-       public void setFocus() {
-               flowsViewer.getTree().setFocus();
-       }
-
        @Override
        public void dispose() {
                JcrUtils.unregisterQuietly(processNode, statusObserver);
@@ -367,20 +450,7 @@ public class ProcessBuilderPage extends FormPage implements SlcNames, SlcTypes {
                @Override
                public boolean validateDrop(Object target, int operation,
                                TransferData transferType) {
-                       return true;
+                       return isEditable(getProcessStatus());
                }
        }
-
-       class StatusObserver implements EventListener {
-
-               public void onEvent(EventIterator events) {
-                       PlatformUI.getWorkbench().getDisplay().asyncExec(new Runnable() {
-                               public void run() {
-                                       status.setText(getProcessStatus());
-                               }
-                       });
-                       // flowsViewer.refresh();
-               }
-
-       }
 }
index 4da6f061a849061467a42c6281632a1579b46e3c..e898a64a12d69b04a523ebddcf84d876ca3c62bc 100644 (file)
@@ -1,7 +1,5 @@
 package org.argeo.slc.client.ui.editors;
 
-import java.util.Calendar;
-import java.util.GregorianCalendar;
 import java.util.UUID;
 
 import javax.jcr.Node;
@@ -15,7 +13,7 @@ import org.argeo.slc.SlcException;
 import org.argeo.slc.client.ui.ClientUiPlugin;
 import org.argeo.slc.client.ui.controllers.ProcessController;
 import org.argeo.slc.execution.ExecutionProcess;
-import org.argeo.slc.jcr.SlcJcrConstants;
+import org.argeo.slc.jcr.SlcJcrUtils;
 import org.argeo.slc.jcr.SlcNames;
 import org.argeo.slc.jcr.SlcTypes;
 import org.eclipse.core.runtime.IProgressMonitor;
@@ -33,7 +31,7 @@ public class ProcessEditor extends FormEditor implements SlcTypes, SlcNames {
 
        private ProcessBuilderPage builderPage;
        private ProcessLogPage logPage;
-       
+
        @Override
        public void init(IEditorSite site, IEditorInput input)
                        throws PartInitException {
@@ -58,13 +56,11 @@ public class ProcessEditor extends FormEditor implements SlcTypes, SlcNames {
 
        protected Node newProcessNode(ProcessEditorInput pei)
                        throws RepositoryException {
-               Calendar now = new GregorianCalendar();
                String uuid = UUID.randomUUID().toString();
-               String processPath = SlcJcrConstants.PROCESSES_BASE_PATH + '/'
-                               + JcrUtils.dateAsPath(now, true) + uuid;
+               String processPath = SlcJcrUtils.createExecutionProcessPath(uuid);
                Node processNode = JcrUtils.mkdirs(session, processPath, SLC_PROCESS);
                processNode.setProperty(SLC_UUID, uuid);
-               processNode.setProperty(SLC_STATUS, ExecutionProcess.UNINITIALIZED);
+               processNode.setProperty(SLC_STATUS, ExecutionProcess.NEW);
                Node processFlow = processNode.addNode(SLC_FLOW);
                processFlow.addMixin(SLC_REALIZED_FLOW);
 
@@ -79,6 +75,22 @@ public class ProcessEditor extends FormEditor implements SlcTypes, SlcNames {
                return processNode;
        }
 
+       @Override
+       public boolean isDirty() {
+               if (getProcessStatus().equals(ExecutionProcess.NEW))
+                       return true;
+               return super.isDirty();
+       }
+
+       protected String getProcessStatus() {
+               try {
+                       return processNode.getProperty(SLC_STATUS).getString();
+               } catch (RepositoryException e) {
+                       throw new SlcException("Cannot retrieve status for " + processNode,
+                                       e);
+               }
+       }
+
        @Override
        public void dispose() {
                JcrUtils.logoutQuietly(session);
@@ -114,12 +126,12 @@ public class ProcessEditor extends FormEditor implements SlcTypes, SlcNames {
        public void doSave(IProgressMonitor monitor) {
                try {
                        String status = processNode.getProperty(SLC_STATUS).getString();
-                       if (status.equals(ExecutionProcess.UNINITIALIZED))
+                       if (status.equals(ExecutionProcess.NEW))
                                processNode.setProperty(SLC_STATUS,
                                                ExecutionProcess.INITIALIZED);
                        session.save();
                        builderPage.commit(true);
-                       firePropertyChange(PROP_DIRTY);
+                       editorDirtyStateChanged();
                } catch (RepositoryException e) {
                        throw new SlcException("Cannot save " + processNode, e);
                } finally {
index 9a94566da68ceeef2bfa95097428c8ea347c366c..f93af3feda22903121c0a3ce6ae603f408908c74 100644 (file)
@@ -74,4 +74,14 @@ public class ProcessEditorInput implements IEditorInput, IPersistableElement {
                return launchImmediately;
        }
 
+       @Override
+       public boolean equals(Object obj) {
+               if (!(obj instanceof ProcessEditorInput))
+                       return false;
+               ProcessEditorInput pei = (ProcessEditorInput) obj;
+               if (processPath != null && pei.processPath != null)
+                       return processPath.equals(pei.processPath);
+               return false;
+       }
+
 }
index 8c2bb40079ff5c9c38b84365e2cfb49cbadfd8fc..ddc34a581943f63ed47d898436261e6c449fd70c 100644 (file)
@@ -1,5 +1,7 @@
 package org.argeo.slc.client.ui.views;
 
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
 import java.util.ArrayList;
 import java.util.List;
 
@@ -52,6 +54,10 @@ public class JcrProcessListView extends ViewPart {
 
        private EventListener processesObserver;
 
+       private DateFormat dateFormat = new SimpleDateFormat(
+                       "EEE, dd MMM yyyy HH:mm:ss");
+       private Integer queryLimit = 100;
+
        public void createPartControl(Composite parent) {
                Table table = createTable(parent);
                viewer = new TableViewer(table);
@@ -127,6 +133,8 @@ public class JcrProcessListView extends ViewPart {
                                String sql = "SELECT * from [slc:process] ORDER BY [jcr:lastModified] DESC";
                                Query query = session.getWorkspace().getQueryManager()
                                                .createQuery(sql, Query.JCR_SQL2);
+                               // TODO paging
+                               query.setLimit(queryLimit);
                                List<Node> nodes = new ArrayList<Node>();
                                for (NodeIterator nit = query.execute().getNodes(); nit
                                                .hasNext();) {
@@ -150,7 +158,6 @@ public class JcrProcessListView extends ViewPart {
                        ITableLabelProvider {
 
                public Image getColumnImage(Object element, int columnIndex) {
-                       // TODO Auto-generated method stub
                        return null;
                }
 
@@ -160,7 +167,9 @@ public class JcrProcessListView extends ViewPart {
                                switch (index) {
 
                                case 0:
-                                       return node.getProperty(Property.JCR_CREATED).getString();
+                                       return dateFormat.format(node
+                                                       .getProperty(Property.JCR_LAST_MODIFIED).getDate()
+                                                       .getTime());
                                case 1:
                                        return "local";
                                case 2:
index 58393dd9007fd243d29e9d7dd3169988d96cad10..35a84fb7b7a6af94d266ee0abdc432a4be66470e 100644 (file)
@@ -9,7 +9,7 @@ package org.argeo.slc.execution;
  */
 public interface ExecutionProcess {
        /** The process is not yet usable. */
-       public final static String UNINITIALIZED = "UNINITIALIZED";
+       public final static String NEW = "NEW";
        /** The process is usable but not yet scheduled to run. */
        public final static String INITIALIZED = "INITIALIZED";
        /** The process is usable and scheduled to run, but not yet running. */
index 37b647ad320281f94dfd6e05ef9185d0e3a0c04f..d11f99922aaca768bcda82a45b73cadbe91f15d9 100644 (file)
@@ -34,7 +34,7 @@ public class SlcExecution implements ExecutionProcess, Serializable {
        private String host;\r
        private String user;\r
        private String type;\r
-       private String status = UNINITIALIZED;\r
+       private String status = NEW;\r
        private Map<String, String> attributes = new TreeMap<String, String>();\r
 \r
        /** TODO: Synchronize */\r
index 0cda5a86d68e3d6149163633c907cab67bc3474b..ed2294f30087a45066a3799f706fa5d788312401 100644 (file)
@@ -1,5 +1,10 @@
 package org.argeo.slc.jcr;
 
+import java.util.Calendar;
+import java.util.GregorianCalendar;
+
+import org.argeo.jcr.JcrUtils;
+
 /** Utilities around the SLC JCR model. Note that it relies on fixed base paths. */
 public class SlcJcrUtils {
        public final static Integer AGENT_FACTORY_DEPTH = 3;
@@ -39,6 +44,14 @@ public class SlcJcrUtils {
                return buf.toString();
        }
 
+       /** Create a new execution process path based on the current time */
+       public static String createExecutionProcessPath(String uuid) {
+               Calendar now = new GregorianCalendar();
+               return SlcJcrConstants.PROCESSES_BASE_PATH + '/'
+                               + JcrUtils.dateAsPath(now, true) + uuid;
+
+       }
+
        /** Prevents instantiation */
        private SlcJcrUtils() {
 
index 998027e8efbc44265dbc9f5d9e68f99ef511bd97..ce08b8f38136d432617b8b7e8abcb2d145c82143 100644 (file)
@@ -35,6 +35,9 @@ public class JcrExecutionProcess implements ExecutionProcess {
        public void setStatus(String status) {
                try {
                        node.setProperty(SlcNames.SLC_STATUS, status);
+                       // last modified properties needs to be manually updated
+                       // see https://issues.apache.org/jira/browse/JCR-2233
+                       JcrUtils.updateLastModified(node);
                        node.getSession().save();
                } catch (RepositoryException e) {
                        try {