001: /*
002: * Copyright 1990-2006 Sun Microsystems, Inc. All Rights Reserved.
003: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER
004: *
005: * This program is free software; you can redistribute it and/or
006: * modify it under the terms of the GNU General Public License version
007: * 2 only, as published by the Free Software Foundation.
008: *
009: * This program is distributed in the hope that it will be useful, but
010: * WITHOUT ANY WARRANTY; without even the implied warranty of
011: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
012: * General Public License version 2 for more details (a copy is
013: * included at /legal/license.txt).
014: *
015: * You should have received a copy of the GNU General Public License
016: * version 2 along with this work; if not, write to the Free Software
017: * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
018: * 02110-1301 USA
019: *
020: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
021: * Clara, CA 95054 or visit www.sun.com if you need additional
022: * information or have any questions.
023: */
024:
025: package com.sun.jumpimpl.executive;
026:
027: import java.io.IOException;
028: import java.util.Enumeration;
029: import java.util.Iterator;
030: import java.util.Map;
031: import java.util.Vector;
032: import com.sun.jump.command.JUMPCommand;
033: import com.sun.jump.command.JUMPIsolateLifecycleRequest;
034: import com.sun.jump.common.JUMPAppModel;
035: import com.sun.jump.common.JUMPProcessProxy;
036: import com.sun.jump.executive.*;
037: import com.sun.jump.message.*;
038: import com.sun.jump.module.JUMPModule;
039: import com.sun.jump.os.JUMPOSInterface;
040:
041: import com.sun.jumpimpl.process.JUMPIsolateProxyImpl;
042: import com.sun.jumpimpl.process.JUMPProcessProxyImpl;
043: import com.sun.jumpimpl.process.RequestSenderHelper;
044: import com.sun.jumpimpl.process.JUMPModulesConfig;
045:
046: public class IsolateFactoryImpl implements JUMPIsolateFactory,
047: JUMPMessageHandler {
048:
049: private Vector processes;
050: private Vector isolates;
051: private JUMPMessageDispatcher dispatcher;
052: private JUMPExecutive exec;
053: private RequestSenderHelper rsh;
054: private Object messageRegistration;
055: private String isolateExtraArg;
056: private String defaultVMArgs;
057:
058: IsolateFactoryImpl() {
059: exec = JUMPExecutive.getInstance();
060: dispatcher = exec.getMessageDispatcher();
061: rsh = new RequestSenderHelper(exec);
062: processes = new Vector();
063: isolates = new Vector();
064:
065: Map config = JUMPModulesConfig.getProperties();
066:
067: //
068: // Get the default VM arguments from config
069: //
070: defaultVMArgs = (String) config.get("vm.args");
071:
072: //
073: // Get all isolatemanager command messages here.
074: //
075: try {
076: String type = JUMPIsolateLifecycleRequest.MESSAGE_TYPE;
077: messageRegistration = dispatcher
078: .registerHandler(type, this );
079: } catch (Throwable e) {
080: e.printStackTrace();
081: throw new RuntimeException(
082: "Lifecycle module initialization failed");
083: }
084:
085: isolateExtraArg = (String) config
086: .get("runtime-properties-file");
087: }
088:
089: /**
090: * Create new isolate conforming to <code>model</code>,
091: * and with additional VM arugments.
092: */
093: public JUMPIsolateProxy newIsolate(JUMPAppModel model, String vmArgs) {
094: String vmArgs0 = "";
095: if (defaultVMArgs != null && !defaultVMArgs.equals("")) {
096: vmArgs0 = defaultVMArgs.trim() + " ";
097: }
098: if (vmArgs != null) {
099: vmArgs0 = vmArgs0 + vmArgs.trim();
100: }
101:
102: String args[];
103: if (isolateExtraArg == null) {
104: args = new String[] { vmArgs0, model.getName() };
105: } else {
106: args = new String[] { vmArgs0, model.getName(),
107: isolateExtraArg };
108: }
109:
110: // The following is inherently racy, but it is handled properly.
111: //
112: // 1) The process is created
113: // 2) The representative JUMPIsolateProxyImpl is created.
114: //
115: // Between #1 and #2, the "initialized" message might come in
116: // from the newly created process, and will be looking for the isolate
117: // object JUMPIsolateProxyImpl that matches the pid. If the instance
118: // is not registered yet, we have a problem.
119: //
120: // The solution is to have the message handler and newIsolate()
121: // race to register the isolate object for the pid.
122: // One of them will always win out, and there will still be
123: // only one isolate object for each pid.
124: //
125: int pid = JUMPOSInterface.getInstance().createProcess(args);
126: if (pid == -1) {
127: /* failed to create process */
128: throw new RuntimeException("Failed to the isolate process");
129: }
130:
131: JUMPIsolateProxyImpl isolate = JUMPIsolateProxyImpl
132: .registerIsolate(pid);
133: isolates.add(isolate);
134:
135: //
136: // Wait until isolate is initialized (it will send us a message
137: // when it is ready)
138: //
139: // FIXME: what's the right timeout value and where is that stored?
140: isolate.waitForState(
141: JUMPIsolateLifecycleRequest.ISOLATE_STATE_INITIALIZED,
142: 5000L);
143:
144: // Tell the isolate about the ixc port.
145: // FIXME: should go away once ixc is on messaging.
146: rsh.sendRequest(isolate, new com.sun.jumpimpl.ixc.IxcMessage(
147: com.sun.jumpimpl.ixc.ConnectionReceiver
148: .getExecVMServicePort()));
149:
150: //
151: // FIXME!!!! What happens if we time out? We can kill
152: // the isolate and return null?
153: // Or we can make newIsolate() return some sort of error code
154: // and allow a re-try? Must figure this out
155: //
156: return isolate;
157: }
158:
159: /**
160: * Create new isolate conforming to <code>model</code>
161: */
162: public JUMPIsolateProxy newIsolate(JUMPAppModel model) {
163: return newIsolate(model, null);
164: }
165:
166: /**
167: * Returns the <code>JUMPIsolate</code> associated with the isolate id.
168: * It returns <Code>null</code> if no such isolate is found.
169: */
170: public JUMPIsolateProxy getIsolate(int isolateId) {
171: return JUMPIsolateProxyImpl.getRegisteredIsolate(isolateId);
172: }
173:
174: /**
175: * Returns all the active and running isolates.
176: */
177: public JUMPIsolateProxy[] getActiveIsolates() {
178: Vector activeIsolates = new Vector();
179: Iterator i = isolates.iterator();
180: //
181: // FIXME: what state should this call be looking at?
182: // All created isolates? All initialized isolates? All running?
183: //
184: // FIXME: Need synchronization here on "isolates".
185: //
186: while (i.hasNext()) {
187: JUMPIsolateProxyImpl isolate = ((JUMPIsolateProxyImpl) i
188: .next());
189: if (isolate.isAlive()) {
190: activeIsolates.add(isolate);
191: }
192: }
193:
194: return (JUMPIsolateProxy[]) activeIsolates
195: .toArray(new JUMPIsolateProxy[] {});
196: }
197:
198: public void handleMessage(JUMPMessage m) {
199: JUMPCommand raw = JUMPIsolateLifecycleRequest.fromMessage(m);
200: JUMPIsolateLifecycleRequest request = (JUMPIsolateLifecycleRequest) raw;
201:
202: String requestId = request.getCommandId();
203:
204: //
205: // FIXME: the isolate object should created automatically by the
206: // JUMPIsolateLifecycleRequest class. To ensure that, however,
207: // requires that getIsolate() be available both on the client
208: // and the executive side.
209: //
210: String initId = JUMPIsolateLifecycleRequest.ID_ISOLATE_INITIALIZED;
211: String destroyedId = JUMPIsolateLifecycleRequest.ID_ISOLATE_DESTROYED;
212:
213: int initState = JUMPIsolateLifecycleRequest.ISOLATE_STATE_INITIALIZED;
214:
215: if (requestId.equals(initId)) {
216: // Construction
217: JUMPIsolateProxyImpl ipi = JUMPIsolateProxyImpl
218: .registerIsolate(request.getIsolateId());
219:
220: //
221: // Make sure proxy reflects state reached by the isolate.
222: // Caller is waiting on this.
223: //
224: ipi.setIsolateState(initState);
225: // No response required on this request.
226: } else if (requestId.equals(destroyedId)) {
227: int pid = request.getIsolateId();
228:
229: JUMPIsolateProxyImpl ipi = JUMPIsolateProxyImpl
230: .getRegisteredIsolate(pid);
231: if (ipi != null) {
232: ipi.setStateToDestroyed();
233: isolates.remove(ipi);
234: }
235: }
236: }
237: }
|