1
/*___INFO__MARK_BEGIN__*/
2
/*************************************************************************
4
* The Contents of this file are made available subject to the terms of
5
* the Sun Industry Standards Source License Version 1.2
7
* Sun Microsystems Inc., March, 2001
10
* Sun Industry Standards Source License Version 1.2
11
* =================================================
12
* The contents of this file are subject to the Sun Industry Standards
13
* Source License Version 1.2 (the "License"); You may not use this file
14
* except in compliance with the License. You may obtain a copy of the
15
* License at http://gridengine.sunsource.net/Gridengine_SISSL_license.html
17
* Software provided under this License is provided on an "AS IS" basis,
18
* WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
19
* WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
20
* MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
21
* See the License for the specific provisions governing your rights and
22
* obligations concerning the Software.
24
* The Initial Developer of the Original Code is: Sun Microsystems, Inc.
26
* Copyright: 2001 by Sun Microsystems, Inc.
28
* All Rights Reserved.
30
************************************************************************/
31
/*___INFO__MARK_END__*/
32
package com.sun.grid.jgdi.management;
34
import com.sun.grid.jgdi.jni.EventClientImpl;
35
import com.sun.grid.jgdi.jni.JGDIBaseImpl;
36
import java.io.FileInputStream;
37
import java.io.IOException;
38
import java.util.Properties;
39
import java.util.concurrent.locks.ReentrantLock;
40
import java.util.logging.Level;
41
import java.util.logging.LogManager;
42
import javax.management.Notification;
43
import javax.management.ObjectName;
44
import javax.management.MBeanServer;
46
import com.sun.grid.jgdi.management.mbeans.JGDIJMX;
47
import com.sun.grid.jgdi.security.JGDIPrincipal;
49
import java.io.FileOutputStream;
50
import java.io.PrintStream;
51
import java.security.AccessController;
52
import java.util.concurrent.locks.Condition;
53
import java.util.concurrent.locks.Lock;
54
import java.util.logging.LogRecord;
55
import java.util.logging.Logger;
56
import javax.management.NotificationListener;
57
import javax.management.remote.JMXConnectionNotification;
58
import javax.management.remote.JMXConnectorServer;
59
import javax.security.auth.Subject;
62
* JGDI JMX agent class.
64
public class JGDIAgent implements Runnable {
72
private JMXConnectorServer mbeanServerConnector;
73
// Platform MBeanServer used to register your MBeans
75
private MBeanServer mbs;
76
private static File sgeRoot;
77
private static File caTop;
78
private final static Logger log = Logger.getLogger(JGDIAgent.class.getName());
79
private static final JGDIAgent agent = new JGDIAgent();
82
private static String url;
83
private static File jmxDir;
84
private final Lock stateLock = new ReentrantLock();
85
private final Condition stateChangedCondition = stateLock.newCondition();
86
private State state = State.STOPPED;
89
* JGDIAgent can not be instantiate from outside
94
private void setState(State state) {
98
stateChangedCondition.signalAll();
104
public void startMBeanServer() throws Exception {
106
File managementFile = new File(getJmxDir(), "management.properties");
108
log.log(Level.FINE, "loading mbean server configuration from {0}", managementFile);
110
final Properties props = new Properties();
111
props.load(new FileInputStream(managementFile));
113
final String portStr = props.getProperty(ConnectorBootstrap.PropertyNames.PORT);
115
mbeanServerConnector = ConnectorBootstrap.initialize(portStr, props);
116
mbeanServerConnector.addNotificationListener(new MyNotificationListener(), null, null);
117
mbs = mbeanServerConnector.getMBeanServer();
118
log.log(Level.FINE, "starting mbean server");
119
mbeanServerConnector.start();
120
log.log(Level.INFO, "mbean server started (port={0})", portStr);
123
private void stopMBeanServer() {
124
if (mbeanServerConnector != null) {
126
log.log(Level.FINE, "stopping mbean server");
127
mbeanServerConnector.stop();
128
} catch (Exception ex) {
129
log.log(Level.WARNING, "cannot stop mbean server", ex);
134
public static String getUrl() {
136
throw new IllegalStateException("JGDIAgent.url is not initialized");
141
public static File getCaTop() {
143
String str = System.getProperty("com.sun.grid.jgdi.caTop");
145
throw new IllegalStateException("system properties com.sun.grid.jgdi.caTop not found");
147
caTop = new File(str);
152
public static File getSgeRoot() {
153
if (sgeRoot == null) {
154
String sgeRootStr = System.getProperty("com.sun.grid.jgdi.sgeRoot");
155
if (sgeRootStr == null) {
156
throw new IllegalStateException("system properties com.sun.grid.jgdi.sgeRoot not found");
158
sgeRoot = new File(sgeRootStr);
163
public static String getSgeCell() {
164
String ret = System.getProperty("com.sun.grid.jgdi.sgeCell");
166
throw new IllegalStateException("system properties com.sun.grid.jgdi.sgeCell not found");
171
public static File getJmxDir() {
172
if (jmxDir == null) {
173
jmxDir = new File(getSgeRoot(), getSgeCell() + File.separatorChar + "common" + File.separatorChar + "jmx");
178
private MBeanServer getMBeanServer() throws IOException {
180
throw new IllegalStateException("mbean server is not started");
187
EventClientImpl.resetShutdown();
188
JGDIBaseImpl.resetShutdown();
189
setState(State.RUNNING);
191
log.log(Level.FINE, "starting mbean server");
193
} catch (Exception ex) {
194
log.log(Level.SEVERE, "startup of mbean server failed", ex);
198
// The following code blocks until the stop or shutdown methods are called
199
log.log(Level.FINE, "waitForStop");
201
} catch (InterruptedException ex) {
202
log.log(Level.FINE, "JGDIAgent has been interrupted");
204
log.log(Level.INFO, "JGDIAgent is going down");
206
JGDISession.closeAllSessions();
207
EventClientImpl.closeAll();
208
JGDIBaseImpl.closeAllConnections();
210
log.log(Level.FINE, "stopping mbean server");
212
setState(State.STOPPED);
217
public static void main(String[] args) {
219
if (args.length != 1) {
220
log.log(Level.SEVERE, "invalid arguments for JGDIAgent: JGDIAgent <jgdi connect url>");
226
FileOutputStream stdout = new FileOutputStream("jgdi.stdout", true);
227
System.setOut(new PrintStream(stdout, true));
228
log.fine("stdout redirected to jgdi.stdout");
229
} catch (Exception ex) {
230
log.log(Level.WARNING, "cannot redirect stdout to file jgdi.stdout", ex);
233
FileOutputStream stderr = new FileOutputStream("jgdi.stderr", true);
234
System.setErr(new PrintStream(stderr, true));
235
log.fine("stderr redirected to jgdi.stderr");
236
} catch (Exception ex) {
237
log.log(Level.WARNING, "cannot redirect stderr to file jgdi.stderr", ex);
240
Thread t = new Thread(agent);
241
t.setContextClassLoader(agent.getClass().getClassLoader());
244
} catch (Throwable ex) {
245
log.log(Level.SEVERE, "unexpected error in JGDIAgent", ex);
247
log.log(Level.INFO, "JGDIAgent is down");
248
// LogManager.getLogManager().reset();
252
private void waitForStop() throws InterruptedException {
253
log.entering("JGDIAgent", "waitForStop");
256
while (state == State.RUNNING) {
257
stateChangedCondition.await();
262
log.exiting("JGDIAgent", "waitForStop");
266
* Shutdown the JGDIAgent
268
public static void shutdown() {
269
log.entering("JGDIAgent", "shutdown");
270
agent.setState(State.SHUTDOWN);
271
log.exiting("JGDIAgent", "shutdown");
274
public static void start() {
275
log.entering("JGDIAgent", "start");
276
agent.setState(State.START);
277
log.exiting("JGDIAgent", "start");
280
public static void stop() {
281
log.entering("JGDIAgent", "stop");
282
agent.setState(State.STOPPED);
283
log.exiting("JGDIAgent", "stop");
287
* Get the name of the session mbean
288
* @param connectionId the id of the jmx connection
289
* @return name of the session mbean or <code>null</code> if the connection id
290
* does not contain a session id
292
public static ObjectName getObjectNameFromConnectionId(String connectionId) {
293
log.entering("JGDIAgent", "getObjectNameFromConnectionId", connectionId);
294
long sessionId = getSessionIdFromConnectionId(connectionId);
295
ObjectName ret = null;
296
if (sessionId >= 0) {
297
ret = getObjectNameForSessionMBean(sessionId);
299
log.exiting("JGDIAgent", "getObjectNameFromConnectionId", ret);
304
* Get the name of the session mbean
305
* @param sessionId the session id
306
* @return the name of the session mbean
308
public static ObjectName getObjectNameForSessionMBean(long sessionId) {
309
log.entering("JGDIAgent", "getObjectNameForSessionMBean", sessionId);
310
ObjectName ret = null;
312
ret = new ObjectName(String.format("gridengine:type=JGDI,sessionId=%d", sessionId));
313
} catch (Exception ex) {
314
IllegalStateException ilse = new IllegalStateException("Invalid object name", ex);
315
log.throwing("JGDIAgent", "getObjectNameForSessionMBean", ilse);
318
log.exiting("JGDIAgent", "getObjectNameForSessionMBean", ret);
323
* Get the session id out of the connection id
324
* @param connectionId the connection id
325
* @return the session id of <code>-1</code> if the connection id does not contain a session id
327
public static long getSessionIdFromConnectionId(String connectionId) {
328
log.entering("JGDIAgent", "getSessionIdFromConnectionId", connectionId);
330
int startIndex = connectionId.indexOf(JGDIPrincipal.SESSION_ID_PREFIX);
331
if (startIndex >= 0) {
332
startIndex += JGDIPrincipal.SESSION_ID_PREFIX.length();
333
int endIndex = connectionId.indexOf(JGDIPrincipal.SESSION_ID_SUFFIX, startIndex);
335
String sessionIdStr = connectionId.substring(startIndex, endIndex);
337
log.log(Level.FINE, "sessionIdStr = {0}", sessionIdStr);
338
ret = Long.parseLong(sessionIdStr);
339
} catch (NumberFormatException ex) {
340
log.log(Level.WARNING, "Got invalid sessionId ({0})", sessionIdStr);
343
log.log(Level.WARNING, "end of sessionId not found in connectionId ({0})", connectionId);
346
log.log(Level.WARNING, "sessionId not found in connectionId ({0})", connectionId);
349
log.log(Level.WARNING, "jmx connection id does not contain a jgdi session id: {0}", connectionId);
351
log.exiting("JGDIAgent", "getSessionIdFromConnectionId", ret);
355
private void registerSessionMBean(JGDISession session) {
356
log.entering("JGDIAgent", "registerSessionMBean", session);
358
JGDIJMX mbean = new JGDIJMX(session);
359
ObjectName mbeanName = getObjectNameForSessionMBean(session.getId());
360
getMBeanServer().registerMBean(mbean, mbeanName);
361
log.log(Level.FINE, "mbean for session {0} registered", session.getId());
362
} catch (Exception ex) {
363
LogRecord lr = new LogRecord(Level.WARNING, "Can not register mbean for session {0}");
364
lr.setParameters(new Object[]{session.getId()});
368
log.exiting("JGDIAgent", "registerSessionMBean");
371
private void unregisterSessionMBean(JGDISession session) {
372
log.entering("JGDIAgent", "unregisterSessionMBean", session);
374
ObjectName mbeanName = getObjectNameForSessionMBean(session.getId());
375
getMBeanServer().unregisterMBean(mbeanName);
376
log.log(Level.FINE, "mbean for session {0} unregistered", session.getId());
377
} catch (Exception ex) {
378
LogRecord lr = new LogRecord(Level.WARNING, "Can not unregister mbean for session {0}");
379
lr.setParameters(new Object[]{session.getId()});
383
log.exiting("JGDIAgent", "unregisterSessionMBean");
386
class MyNotificationListener implements NotificationListener {
388
public void handleNotification(Notification notification, Object handback) {
390
if (notification instanceof JMXConnectionNotification) {
392
JMXConnectionNotification jn = (JMXConnectionNotification) notification;
394
if (log.isLoggable(Level.FINE)) {
395
Subject sub = Subject.getSubject(AccessController.getContext());
396
log.log(Level.FINE, "Got notification from client {0}, subject = {1}", new Object[]{jn.getConnectionId(), sub});
399
long sessionId = getSessionIdFromConnectionId(jn.getConnectionId());
400
if (sessionId >= 0) {
401
if (JMXConnectionNotification.CLOSED.equals(jn.getType())) {
402
log.log(Level.FINE, "client connection {0} closed", jn.getConnectionId());
403
JGDISession session = JGDISession.closeSession(sessionId);
404
if (session != null) {
405
unregisterSessionMBean(session);
407
} else if (JMXConnectionNotification.FAILED.equals(jn.getType())) {
408
log.log(Level.FINE, "client connection {0} failed", jn.getConnectionId());
409
JGDISession session = JGDISession.closeSession(sessionId);
410
if (session != null) {
411
unregisterSessionMBean(session);
413
} else if (JMXConnectionNotification.NOTIFS_LOST.equals(jn.getType())) {
414
log.log(Level.WARNING, "client connection {0} losts notification", jn.getConnectionId());
415
} else if (JMXConnectionNotification.OPENED.equals(jn.getType())) {
416
if (log.isLoggable(Level.FINE)) {
417
log.log(Level.FINE, "client connection {0} opened", new Object[]{jn.getConnectionId()});
419
JGDISession session = JGDISession.createNewSession(sessionId, url);
420
registerSessionMBean(session);
423
log.log(Level.WARNING, "Got a jmx connection without a session id: {0}", jn.getConnectionId());