From: <st...@us...> - 2011-06-30 14:33:31
|
Revision: 8683 http://smartfrog.svn.sourceforge.net/smartfrog/?rev=8683&view=rev Author: steve_l Date: 2011-06-30 14:33:24 +0000 (Thu, 30 Jun 2011) Log Message: ----------- SFOS-1622 SFOS-1623 add ping and terminate operations to the grinstall tasks Modified Paths: -------------- trunk/core/components/grinstall/src/org/smartfrog/services/groovy/install/Component.groovy trunk/core/components/grinstall/src/org/smartfrog/services/groovy/install/IComponent.groovy trunk/core/components/grinstall/src/org/smartfrog/services/groovy/install/base.sf trunk/core/components/grinstall/src/org/smartfrog/services/groovy/install/task/DelegatingScript.groovy trunk/core/components/grinstall/src/org/smartfrog/services/groovy/install/task/GroovyTask.groovy trunk/core/components/grinstall/src/org/smartfrog/services/groovy/install/task/ITask.groovy trunk/core/components/grinstall/test/org/smartfrog/services/groovy/test/system/examples/components.sf Added Paths: ----------- trunk/core/components/grinstall/test/examples/touchfile/ping.groovy trunk/core/components/grinstall/test/examples/touchfile/terminate.groovy Modified: trunk/core/components/grinstall/src/org/smartfrog/services/groovy/install/Component.groovy =================================================================== --- trunk/core/components/grinstall/src/org/smartfrog/services/groovy/install/Component.groovy 2011-06-30 10:20:54 UTC (rev 8682) +++ trunk/core/components/grinstall/src/org/smartfrog/services/groovy/install/Component.groovy 2011-06-30 14:33:24 UTC (rev 8683) @@ -10,6 +10,8 @@ import org.smartfrog.sfcore.common.SmartFrogResolutionException import org.smartfrog.sfcore.compound.CompoundImpl import org.smartfrog.sfcore.prim.Prim +import org.smartfrog.sfcore.prim.TerminationRecord +import org.smartfrog.sfcore.utils.SmartFrogThread import org.smartfrog.sfcore.utils.WorkflowThread /** @@ -21,6 +23,7 @@ private ComponentState componentState public File destDir private Executor executor; + int terminationTimeout = 20000 public Component() throws RemoteException { @@ -104,7 +107,6 @@ } } - } /** @@ -115,24 +117,26 @@ enterState(ComponentState.REMOVED) } - private void executeNextChild() { + private boolean executeNextChild() { ComponentState currentState = getComponentState(); + boolean result = false; switch (currentState) { case ComponentState.REMOVED: - run(ATTR_INSTALL) + result = run(ATTR_INSTALL) break case ComponentState.INSTALLED: - run(ATTR_PRE_CONFIGURE) + result = run(ATTR_PRE_CONFIGURE) break case ComponentState.PRECONFIGURED: - run(ATTR_START) + result = run(ATTR_START) break case ComponentState.STARTED: - run(ATTR_POST_CONFIGURE) + result = run(ATTR_POST_CONFIGURE) break default: - return + result = false } + return result; } /** @@ -140,10 +144,10 @@ * @param task * @throws SmartFrogResolutionException if the task is missing or of the wrong type */ - private void run(String task) { + private boolean run(String task) { def taskObject = sfResolve(task) if (taskObject instanceof ITask) { - taskObject.run() + return taskObject.run() } else { throw new SmartFrogResolutionException("Value of attribute ${task} is not of class ITask") } @@ -178,7 +182,7 @@ private void enterState(ComponentState state) { setComponentState(state) - if(sfLog().debugEnabled) sfLog().debug("new state: " + getComponentState()) + if (sfLog().debugEnabled) sfLog().debug("new state: " + getComponentState()) sfReplaceAttribute(ATTR_STATE, getComponentState()) } @@ -205,5 +209,16 @@ } } + @Override + protected synchronized void sfTerminateWith(TerminationRecord status) { + super.sfTerminateWith(status) + SmartFrogThread.requestAndWaitForThreadTermination(executor, terminationTimeout) + //now try to execute the terminator. Note that it is pre-constructed, and just needs executing + ITask terminator = (ITask) sfResolve(ATTR_TERMINATOR, (Prim) null, false); + if (terminator != null) { + terminator.run(); + } + } + } \ No newline at end of file Modified: trunk/core/components/grinstall/src/org/smartfrog/services/groovy/install/IComponent.groovy =================================================================== --- trunk/core/components/grinstall/src/org/smartfrog/services/groovy/install/IComponent.groovy 2011-06-30 10:20:54 UTC (rev 8682) +++ trunk/core/components/grinstall/src/org/smartfrog/services/groovy/install/IComponent.groovy 2011-06-30 14:33:24 UTC (rev 8683) @@ -19,6 +19,7 @@ String ATTR_START = "start" String ATTR_STATE = "state" String ATTR_EXEC_TIMEOUT = "execTimeout"; + public String ATTR_TERMINATOR = "terminate" String getDestDir() throws RemoteException Modified: trunk/core/components/grinstall/src/org/smartfrog/services/groovy/install/base.sf =================================================================== --- trunk/core/components/grinstall/src/org/smartfrog/services/groovy/install/base.sf 2011-06-30 10:20:54 UTC (rev 8682) +++ trunk/core/components/grinstall/src/org/smartfrog/services/groovy/install/base.sf 2011-06-30 14:33:24 UTC (rev 8683) @@ -14,8 +14,17 @@ /* name of the file that contains a script */ file TBD; + pingable false; } +/** + * A ping task has its script executed on every liveness check, and + * nothing else + */ +PingTask extends Task { + pingable true; +} + // copy a file or directory Source extends Prim { sfClass "org.smartfrog.services.groovy.install.download.Source"; @@ -68,5 +77,17 @@ description "Actions to take after starting a component" file "postConfigure.groovy"; } + + terminate extends Task { + description "Actions to take when terminating the component" + file "terminate.groovy"; + } + + ping extends PingTask { + description "A liveness check" + file "ping.groovy"; + } + + } Modified: trunk/core/components/grinstall/src/org/smartfrog/services/groovy/install/task/DelegatingScript.groovy =================================================================== --- trunk/core/components/grinstall/src/org/smartfrog/services/groovy/install/task/DelegatingScript.groovy 2011-06-30 10:20:54 UTC (rev 8682) +++ trunk/core/components/grinstall/src/org/smartfrog/services/groovy/install/task/DelegatingScript.groovy 2011-06-30 14:33:24 UTC (rev 8683) @@ -90,6 +90,8 @@ } } + + @Override Object run() { sfLog.info("In the script runner of $this") Modified: trunk/core/components/grinstall/src/org/smartfrog/services/groovy/install/task/GroovyTask.groovy =================================================================== --- trunk/core/components/grinstall/src/org/smartfrog/services/groovy/install/task/GroovyTask.groovy 2011-06-30 10:20:54 UTC (rev 8682) +++ trunk/core/components/grinstall/src/org/smartfrog/services/groovy/install/task/GroovyTask.groovy 2011-06-30 14:33:24 UTC (rev 8683) @@ -10,6 +10,7 @@ import org.smartfrog.sfcore.common.SmartFrogLifecycleException import org.smartfrog.sfcore.prim.Prim import org.smartfrog.sfcore.prim.PrimImpl +import org.smartfrog.sfcore.common.SmartFrogLivenessException /** * User: koenigbe @@ -25,38 +26,65 @@ private List<ITask> observers = new ArrayList<ITask>() private final Object lock = new Object() - def utils = new ComponentUtils() + ComponentUtils utils = new ComponentUtils() Prim parent + String file + File scriptDir + String scriptDirName + Script script + File scriptFile + boolean pingable public GroovyTask() throws RemoteException { } + @Override + synchronized void sfStart() { + super.sfStart() + parent = sfParent() + GroovyComponentHelper helper = new GroovyComponentHelper(parent) + file = sfResolve(ATTR_FILE, "", false) + scriptDirName = helper.resolvePath(IComponent.ATTR_SCRIPT_DIR, true) + scriptDir = new File(scriptDirName) + previousTasks = sfResolve(ATTR_PRECONDITIONS, new Vector(), false) + scriptFile = new File(scriptDir, file) + + pingable = sfResolve(ATTR_PINGABLE, false, false); + if (pingable) { + script = loadScript(scriptDir, file) + + } + } + /** - * Implement {@link ITask#run()} + * Implement {@link ITask#run()}. A pingable task returns false + * @return true if the operation executed, and returned true itself * @throws RemoteException * @throws SmartFrogException */ @Override - public void run() throws RemoteException, SmartFrogException { + public boolean run() throws RemoteException, SmartFrogException { + if(pingable) { + return false; + } // ScriptHelper needs component to bind it within task scripts - parent = sfParent() - GroovyComponentHelper helper = new GroovyComponentHelper(parent) if (!sfResolve(ATTR_FINISHED, false, false)) { - String file = sfResolve(ATTR_FILE, "", false) if (file.isEmpty()) { // no task file specified sfLog().debug("No file specified") - return + return false } - String scriptDirName = helper.resolvePath(IComponent.ATTR_SCRIPT_DIR, true); - File scriptDir = new File(scriptDirName) - previousTasks = sfResolve(ATTR_PRECONDITIONS, new Vector(), false) + register() waitForPreconditions() - execute(scriptDir, file) + sfLog().info("Executing file $scriptFile") + boolean result = execute() sfReplaceAttribute(ATTR_FINISHED, true) notifyObservers() + return result; + } else { + return false; } } @@ -105,51 +133,12 @@ /** * Execute a script - * @param scriptDir directory - * @param file file to look for * @return true iff the script was run */ - private boolean execute(File scriptDir, String file) { - sfLog().info("Executing file $file in directory $scriptDir") - File scriptFile = new File(scriptDir, file) - if (!scriptFile.exists()) { - sfLog().info("No script file \"$scriptFile\"") - return false; - } - Component parentComponent = (Component) sfParent() - CompilerConfiguration conf = new CompilerConfiguration() - //set the base class for the script. This will be loaded with a new classloader, so the - //resulting script cannot be cast back to an instance, or invoked with new types. - conf.setScriptBaseClass(DelegatingScript.class.name) - - //instead params are passed down via the binding - Binding binding = new Binding() - binding.setVariable(DelegatingScript.PARENT, parentComponent) - binding.setVariable(DelegatingScript.DESTDIR, new File(parentComponent.getDestDir())) - binding.setVariable(DelegatingScript.SCRIPTDIR, scriptDir) - Script script + private boolean execute() { + script = loadScript(scriptDir, file) try { - ClassLoader loader = this.getClass().getClassLoader() - GroovyShell shell = new GroovyShell(loader, binding, conf) - String text = scriptFile.getText() - script = shell.parse(text) - if (script == null) { - throw new SmartFrogLifecycleException("Null script from parsing $scriptFile") - } - if (sfLog().debugEnabled && !(script instanceof DelegatingScript)) { - def hierarchy = utils.extractClassHierarchy(script) - String message = "Unable to convert the instance $script" + - " into a ${DelegatingScript.class} -- class hierarchy is :\n$hierarchy" - sfLog().debug(message) - } - - } catch (Exception e) { - sfLog().error("When Parsing $scriptFile: $e", e) - throw new SmartFrogExtractedException(SmartFrogExtractedException.convert(e)) - } - try { - script.initialise() - script.run() + script?.run() return true; } catch (Exception e) { sfLog().error("When executing $scriptFile: $e", e) @@ -158,6 +147,47 @@ } + /** + * Load the script file from the filesystem + * @param scriptDir the directory the script exists in + * @param file filename to look for + * @return the script or null + */ + private Script loadScript(File scriptDir, String file) { + + File scriptFile = new File(scriptDir, file) + if (!scriptFile.exists()) { + sfLog().info("No script file \"$scriptFile\"") + script = null; + } else { + Component parentComponent = (Component) sfParent() + CompilerConfiguration conf = new CompilerConfiguration() + //set the base class for the script. This will be loaded with a new classloader, so the + //resulting script cannot be cast back to an instance, or invoked with new types. + conf.setScriptBaseClass(DelegatingScript.class.name) + + //instead params are passed down via the binding + Binding binding = new Binding() + binding.setVariable(DelegatingScript.PARENT, parentComponent) + binding.setVariable(DelegatingScript.DESTDIR, new File(parentComponent.getDestDir())) + binding.setVariable(DelegatingScript.SCRIPTDIR, scriptDir) + + try { + GroovyShell shell = new GroovyShell(this.getClass().getClassLoader(), binding, conf) + String text = scriptFile.getText() + script = shell.parse(text) + if (script == null) { + throw new SmartFrogLifecycleException("Null script from parsing $scriptFile") + } + script.initialise() + } catch (Exception e) { + sfLog().error("When Parsing $scriptFile: $e", e) + throw new SmartFrogExtractedException(SmartFrogExtractedException.convert(e)) + } + } + return script; + } + @Override public void addObserver(ITask observer) throws RemoteException, SmartFrogException { observers.add(observer) @@ -173,4 +203,25 @@ public void update() throws RemoteException, SmartFrogException { unlock() } + + /** + * Execute the ping operation, thrown an exception if there is a problem + */ + void runPing() { + try { + if(pingable) { + script?.run(); + } + } catch (SmartFrogExtractedException e) { + throw new SmartFrogLivenessException(e); + } + } + + @Override + void sfPing(Object source) { + super.sfPing(source) + runPing(); + } + + } \ No newline at end of file Modified: trunk/core/components/grinstall/src/org/smartfrog/services/groovy/install/task/ITask.groovy =================================================================== --- trunk/core/components/grinstall/src/org/smartfrog/services/groovy/install/task/ITask.groovy 2011-06-30 10:20:54 UTC (rev 8682) +++ trunk/core/components/grinstall/src/org/smartfrog/services/groovy/install/task/ITask.groovy 2011-06-30 14:33:24 UTC (rev 8683) @@ -4,6 +4,7 @@ import java.rmi.RemoteException import org.smartfrog.sfcore.common.SmartFrogException import org.smartfrog.sfcore.prim.Prim +import org.smartfrog.sfcore.common.SmartFrogLivenessException /** * User: koenigbe @@ -12,7 +13,7 @@ */ public interface ITask extends Prim, Remote { - void run() throws RemoteException, SmartFrogException + boolean run() throws RemoteException, SmartFrogException void addObserver(ITask observer) throws RemoteException, SmartFrogException @@ -20,10 +21,12 @@ void update() throws RemoteException, SmartFrogException + /** * An attribute that is set when a task is finished. */ String ATTR_FINISHED = "finished" String ATTR_FILE = "file" + String ATTR_PINGABLE = "pingable" String ATTR_PRECONDITIONS = "preconditions" } Added: trunk/core/components/grinstall/test/examples/touchfile/ping.groovy =================================================================== --- trunk/core/components/grinstall/test/examples/touchfile/ping.groovy (rev 0) +++ trunk/core/components/grinstall/test/examples/touchfile/ping.groovy 2011-06-30 14:33:24 UTC (rev 8683) @@ -0,0 +1,2 @@ +package examples.touchfile +helper.touch(component.destDir, "ping.txt") Copied: trunk/core/components/grinstall/test/examples/touchfile/terminate.groovy (from rev 8674, trunk/core/components/grinstall/test/examples/touchfile/install.groovy) =================================================================== --- trunk/core/components/grinstall/test/examples/touchfile/terminate.groovy (rev 0) +++ trunk/core/components/grinstall/test/examples/touchfile/terminate.groovy 2011-06-30 14:33:24 UTC (rev 8683) @@ -0,0 +1,2 @@ +package examples.touchfile +helper.touch(component.destDir, "terminate.txt") Modified: trunk/core/components/grinstall/test/org/smartfrog/services/groovy/test/system/examples/components.sf =================================================================== --- trunk/core/components/grinstall/test/org/smartfrog/services/groovy/test/system/examples/components.sf 2011-06-30 10:20:54 UTC (rev 8682) +++ trunk/core/components/grinstall/test/org/smartfrog/services/groovy/test/system/examples/components.sf 2011-06-30 14:33:24 UTC (rev 8683) @@ -50,6 +50,10 @@ postconfigureExists extends targetExists { name "postconfigure.txt" } + + terminateExists extends targetExists { + name "terminate.txt" + } } } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |