private void callStartExpr(Call call, InputChannel ichannel, Process p, Any root, Any context) throws AnyException { // The call isn't handled in the conventional sense. This is because // we want to *resolve* the arguments w.r.t the current context // and *call* the function with the context of the root of the // new process's node space, // First, try to resolve the call target. We need to do this // so we can get it's parameter definitions. AbstractInputFunc calledFunc = call.resolveFunc(context, getTransaction()); if (calledFunc == null) throw new AnyException("Could not resolve function " + call); // Note that this is the original fn from the catalog. We want // to set the flag in here.... calledFunc.startUse(); try { // Put the transaction in call.setTransaction(getTransaction()); // Resolve the arguments against the current context Map startArgs = call.resolveArgs(context, calledFunc, getTransaction()); // Put the given input channel and new process on the stack startArgs.replaceItem(ServerConstants.ICHANNEL, ichannel); startArgs.replaceItem(ServerConstants.PROCESS, p); Call.call((Func) calledFunc.cloneAny(), startArgs, root, getTransaction(), calledFunc); } finally { calledFunc.endUse(); } }
public Any exec(Any a) throws AnyException { Any processName = EvalExpr.evalFunc(getTransaction(), a, processName_); Any processType = EvalExpr.evalFunc(getTransaction(), a, processType_); InputChannel inputChannel = (InputChannel) EvalExpr.evalFunc(getTransaction(), a, inputChannel_, InputChannel.class); OutputChannel outputChannel = (OutputChannel) EvalExpr.evalFunc(getTransaction(), a, outputChannel_, OutputChannel.class); BooleanI syncExternal = (BooleanI) EvalExpr.evalFunc(getTransaction(), a, syncExternal_, BooleanI.class); // callOnStart/End are already Call objects, not references // so we don't need to resolve them. if (processName == null) nullOperand(processName_); if (processType == null) nullOperand(processType_); Process parent = null; if (processType.equals(Process.CHILD)) parent = getTransaction().getProcess(); else if (!processType.equals(Process.DETACHED)) throw new AnyException("Illegal process type"); if (inputChannel == null && inputChannel_ != null) nullOperand(inputChannel_); if (syncExternal == null && syncExternal_ != null) nullOperand(syncExternal_); if (outputChannel == null && outputChannel_ != null) nullOperand(outputChannel_); // If no input channel is specified, create a new one. if (inputChannel == null) inputChannel = new AnyChannel(new FIFO(0, ChannelConstants.REFERENCE)); else inputChannel = inputChannel.getUnderlyingChannel(); // Create the new process's node space BasicProcess.RootMap root = new BasicProcess.RootMap(); Transaction t = new PrimaryTransaction(); EventDispatcher ed = new EventDispatcher(); ed.addEventListener(InvokeService.makeInvokeService(EventConstants.INVOKE_SVC, t, root)); ed.addEventListener(new DispatchListener(root, t)); // ExceptionHandler eh = new ExceptionToStream(System.out); ExceptionHandler eh = new ExceptionToFunc(); UserProcess p = new UserProcess( processName, inputChannel, outputChannel, eh, t, root, ed, parent, callOnEnd_); root.setProcess(p); // If the process will be 'shared' by other threads (such as // JMS asynchronous listeners or any threading model behind // client code using AbstractPlugin) then this operand must // be set to true. // The object these threads synchronize on must, of course, // be unique to the new process, so make something new. if (syncExternal != null && syncExternal.getValue()) p.setSync(new AnyObject()); // If there's a start call then run it now in the // spawning process's thread but in the spawned // process's node space if (callOnStart_ != null) { Call callOnStart = (Call) callOnStart_.cloneAny(); callStartExpr(callOnStart, inputChannel, p, root, a); } // Pass on caller's privilege levels Process currProc = getTransaction().getProcess(); // Just for server startup main() currProc can be null if (currProc != null) { p.setRealPrivilegeLevel(currProc.getRealPrivilegeLevel()); p.setEffectivePrivilegeLevel(currProc.getEffectivePrivilegeLevel()); // Start the new process's thread. If there is no calling // process then we assume this class is being run from // code, not script, so in case that code has any concurrency // issues we expect it to call startThread(). p.startThread(); } return p; }