~ubuntu-branches/ubuntu/utopic/gridengine/utopic

« back to all changes in this revision

Viewing changes to source/libs/jgdi/src/com/sun/grid/jgdi/management/JGDIAgent.java

  • Committer: Bazaar Package Importer
  • Author(s): Mark Hymers
  • Date: 2008-06-25 22:36:13 UTC
  • Revision ID: james.westby@ubuntu.com-20080625223613-tvd9xlhuoct9kyhm
Tags: upstream-6.2~beta2
ImportĀ upstreamĀ versionĀ 6.2~beta2

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*___INFO__MARK_BEGIN__*/
 
2
/*************************************************************************
 
3
 *
 
4
 *  The Contents of this file are made available subject to the terms of
 
5
 *  the Sun Industry Standards Source License Version 1.2
 
6
 *
 
7
 *  Sun Microsystems Inc., March, 2001
 
8
 *
 
9
 *
 
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
 
16
 *
 
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.
 
23
 *
 
24
 *   The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 
25
 *
 
26
 *   Copyright: 2001 by Sun Microsystems, Inc.
 
27
 *
 
28
 *   All Rights Reserved.
 
29
 *
 
30
 ************************************************************************/
 
31
/*___INFO__MARK_END__*/
 
32
package com.sun.grid.jgdi.management;
 
33
 
 
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;
 
45
 
 
46
import com.sun.grid.jgdi.management.mbeans.JGDIJMX;
 
47
import com.sun.grid.jgdi.security.JGDIPrincipal;
 
48
import java.io.File;
 
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;
 
60
 
 
61
/**
 
62
 * JGDI JMX agent class.
 
63
 */
 
64
public class JGDIAgent implements Runnable {
 
65
 
 
66
    enum State {
 
67
        STOPPED,
 
68
        START,
 
69
        RUNNING,
 
70
        SHUTDOWN
 
71
    }
 
72
    private JMXConnectorServer mbeanServerConnector;
 
73
    // Platform MBeanServer used to register your MBeans
 
74
 
 
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();
 
80
    // JGDI url string
 
81
 
 
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;
 
87
 
 
88
    /**
 
89
     * JGDIAgent can not be instantiate from outside
 
90
     */
 
91
    private JGDIAgent() {
 
92
    }
 
93
 
 
94
    private void setState(State state) {
 
95
        stateLock.lock();
 
96
        try {
 
97
            this.state = state;
 
98
            stateChangedCondition.signalAll();
 
99
        } finally {
 
100
            stateLock.unlock();
 
101
        }
 
102
    }
 
103
 
 
104
    public void startMBeanServer() throws Exception {
 
105
 
 
106
        File managementFile = new File(getJmxDir(), "management.properties");
 
107
 
 
108
        log.log(Level.FINE, "loading mbean server configuration from {0}", managementFile);
 
109
 
 
110
        final Properties props = new Properties();
 
111
        props.load(new FileInputStream(managementFile));
 
112
 
 
113
        final String portStr = props.getProperty(ConnectorBootstrap.PropertyNames.PORT);
 
114
 
 
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);
 
121
    }
 
122
 
 
123
    private void stopMBeanServer() {
 
124
        if (mbeanServerConnector != null) {
 
125
            try {
 
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);
 
130
            }
 
131
        }
 
132
    }
 
133
 
 
134
    public static String getUrl() {
 
135
        if (url == null) {
 
136
            throw new IllegalStateException("JGDIAgent.url is not initialized");
 
137
        }
 
138
        return url;
 
139
    }
 
140
    
 
141
    public static File getCaTop() {
 
142
        if (caTop == null) {
 
143
            String str = System.getProperty("com.sun.grid.jgdi.caTop");
 
144
            if (str == null) {
 
145
                throw new IllegalStateException("system properties com.sun.grid.jgdi.caTop not found");
 
146
            }
 
147
            caTop = new File(str);
 
148
        }
 
149
        return caTop;
 
150
    }
 
151
    
 
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");
 
157
            }
 
158
            sgeRoot = new File(sgeRootStr);
 
159
        }
 
160
        return sgeRoot;
 
161
    }
 
162
 
 
163
    public static String getSgeCell() {
 
164
        String ret = System.getProperty("com.sun.grid.jgdi.sgeCell");
 
165
        if (ret == null) {
 
166
            throw new IllegalStateException("system properties com.sun.grid.jgdi.sgeCell not found");
 
167
        }
 
168
        return ret;
 
169
    }
 
170
 
 
171
    public static File getJmxDir() {
 
172
        if (jmxDir == null) {
 
173
            jmxDir = new File(getSgeRoot(), getSgeCell() + File.separatorChar + "common" + File.separatorChar + "jmx");
 
174
        }
 
175
        return jmxDir;
 
176
    }
 
177
 
 
178
    private MBeanServer getMBeanServer() throws IOException {
 
179
        if (mbs == null) {
 
180
            throw new IllegalStateException("mbean server is not started");
 
181
        }
 
182
        return mbs;
 
183
    }
 
184
 
 
185
    public void run() {
 
186
 
 
187
        EventClientImpl.resetShutdown();
 
188
        JGDIBaseImpl.resetShutdown();
 
189
        setState(State.RUNNING);
 
190
        try {
 
191
            log.log(Level.FINE, "starting mbean server");
 
192
            startMBeanServer();
 
193
        } catch (Exception ex) {
 
194
            log.log(Level.SEVERE, "startup of mbean server failed", ex);
 
195
            return;
 
196
        }
 
197
        try {
 
198
            // The following code blocks until the stop or shutdown methods are called
 
199
            log.log(Level.FINE, "waitForStop");
 
200
            waitForStop();
 
201
        } catch (InterruptedException ex) {
 
202
            log.log(Level.FINE, "JGDIAgent has been interrupted");
 
203
        } finally {
 
204
            log.log(Level.INFO, "JGDIAgent is going down");
 
205
            try {
 
206
                JGDISession.closeAllSessions();
 
207
                EventClientImpl.closeAll();
 
208
                JGDIBaseImpl.closeAllConnections();
 
209
            } finally {
 
210
                log.log(Level.FINE, "stopping mbean server");
 
211
                stopMBeanServer();
 
212
                setState(State.STOPPED);
 
213
            }
 
214
        }
 
215
    }
 
216
 
 
217
    public static void main(String[] args) {
 
218
        try {
 
219
            if (args.length != 1) {
 
220
                log.log(Level.SEVERE, "invalid arguments for JGDIAgent: JGDIAgent <jgdi connect url>");
 
221
                return;
 
222
            }
 
223
            url = args[0];
 
224
 
 
225
            try {
 
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);
 
231
            }
 
232
            try {
 
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);
 
238
            }
 
239
 
 
240
            Thread t = new Thread(agent);
 
241
            t.setContextClassLoader(agent.getClass().getClassLoader());
 
242
            t.start();
 
243
            t.join();
 
244
        } catch (Throwable ex) {
 
245
            log.log(Level.SEVERE, "unexpected error in JGDIAgent", ex);
 
246
        } finally {
 
247
            log.log(Level.INFO, "JGDIAgent is down");
 
248
        // LogManager.getLogManager().reset();
 
249
        }
 
250
    }
 
251
 
 
252
    private void waitForStop() throws InterruptedException {
 
253
        log.entering("JGDIAgent", "waitForStop");
 
254
        stateLock.lock();
 
255
        try {
 
256
            while (state == State.RUNNING) {
 
257
                stateChangedCondition.await();
 
258
            }
 
259
        } finally {
 
260
            stateLock.unlock();
 
261
        }
 
262
        log.exiting("JGDIAgent", "waitForStop");
 
263
    }
 
264
 
 
265
    /**
 
266
     * Shutdown the JGDIAgent
 
267
     */
 
268
    public static void shutdown() {
 
269
        log.entering("JGDIAgent", "shutdown");
 
270
        agent.setState(State.SHUTDOWN);
 
271
        log.exiting("JGDIAgent", "shutdown");
 
272
    }
 
273
 
 
274
    public static void start() {
 
275
        log.entering("JGDIAgent", "start");
 
276
        agent.setState(State.START);
 
277
        log.exiting("JGDIAgent", "start");
 
278
    }
 
279
 
 
280
    public static void stop() {
 
281
        log.entering("JGDIAgent", "stop");
 
282
        agent.setState(State.STOPPED);
 
283
        log.exiting("JGDIAgent", "stop");
 
284
    }
 
285
 
 
286
    /**
 
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
 
291
     */
 
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);
 
298
        }
 
299
        log.exiting("JGDIAgent", "getObjectNameFromConnectionId", ret);
 
300
        return ret;
 
301
    }
 
302
 
 
303
    /**
 
304
     * Get the name of the session mbean
 
305
     * @param sessionId the session id
 
306
     * @return the name of the session mbean
 
307
     */
 
308
    public static ObjectName getObjectNameForSessionMBean(long sessionId) {
 
309
        log.entering("JGDIAgent", "getObjectNameForSessionMBean", sessionId);
 
310
        ObjectName ret = null;
 
311
        try {
 
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);
 
316
            throw ilse;
 
317
        }
 
318
        log.exiting("JGDIAgent", "getObjectNameForSessionMBean", ret);
 
319
        return ret;
 
320
    }
 
321
 
 
322
    /**
 
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
 
326
     */
 
327
    public static long getSessionIdFromConnectionId(String connectionId) {
 
328
        log.entering("JGDIAgent", "getSessionIdFromConnectionId", connectionId);
 
329
        long ret = -1;
 
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);
 
334
            if (endIndex > 0) {
 
335
                String sessionIdStr = connectionId.substring(startIndex, endIndex);
 
336
                try {
 
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);
 
341
                }
 
342
            } else {
 
343
                log.log(Level.WARNING, "end of sessionId not found in connectionId ({0})", connectionId);
 
344
            }
 
345
        } else {
 
346
            log.log(Level.WARNING, "sessionId not found in connectionId ({0})", connectionId);
 
347
        }
 
348
        if (ret < -1) {
 
349
            log.log(Level.WARNING, "jmx connection id does not contain a jgdi session id: {0}", connectionId);
 
350
        }
 
351
        log.exiting("JGDIAgent", "getSessionIdFromConnectionId", ret);
 
352
        return ret;
 
353
    }
 
354
 
 
355
    private void registerSessionMBean(JGDISession session) {
 
356
        log.entering("JGDIAgent", "registerSessionMBean", session);
 
357
        try {
 
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()});
 
365
            lr.setThrown(ex);
 
366
            log.log(lr);
 
367
        }
 
368
        log.exiting("JGDIAgent", "registerSessionMBean");
 
369
    }
 
370
 
 
371
    private void unregisterSessionMBean(JGDISession session) {
 
372
        log.entering("JGDIAgent", "unregisterSessionMBean", session);
 
373
        try {
 
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()});
 
380
            lr.setThrown(ex);
 
381
            log.log(lr);
 
382
        }
 
383
        log.exiting("JGDIAgent", "unregisterSessionMBean");
 
384
    }
 
385
 
 
386
    class MyNotificationListener implements NotificationListener {
 
387
 
 
388
        public void handleNotification(Notification notification, Object handback) {
 
389
 
 
390
            if (notification instanceof JMXConnectionNotification) {
 
391
 
 
392
                JMXConnectionNotification jn = (JMXConnectionNotification) notification;
 
393
 
 
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});
 
397
                }
 
398
 
 
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);
 
406
                        }
 
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);
 
412
                        }
 
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()});
 
418
                        }
 
419
                        JGDISession session = JGDISession.createNewSession(sessionId, url);
 
420
                        registerSessionMBean(session);
 
421
                    }
 
422
                } else {
 
423
                    log.log(Level.WARNING, "Got a jmx connection without a session id: {0}", jn.getConnectionId());
 
424
                }
 
425
            }
 
426
        }
 
427
    }
 
428
}
 
429