ServerTableEntry.java revision 608:7e06bf1dcb09
1/*
2 * Copyright (c) 1997, 2003, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.  Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25package com.sun.corba.se.impl.activation;
26
27/**
28 *
29 * @author      Anita Jindal
30 * @since       JDK1.2
31 */
32
33import org.omg.CORBA.CompletionStatus;
34
35import com.sun.corba.se.spi.activation.Server;
36import com.sun.corba.se.spi.activation.EndPointInfo;
37import com.sun.corba.se.spi.activation.ORBAlreadyRegistered;
38import com.sun.corba.se.spi.activation.ORBPortInfo;
39import com.sun.corba.se.spi.activation.InvalidORBid;
40import com.sun.corba.se.spi.activation.ServerHeldDown;
41import com.sun.corba.se.spi.activation.RepositoryPackage.ServerDef;
42import com.sun.corba.se.spi.activation.IIOP_CLEAR_TEXT;
43import com.sun.corba.se.spi.orb.ORB ;
44
45import com.sun.corba.se.impl.orbutil.ORBConstants;
46import com.sun.corba.se.impl.logging.ActivationSystemException ;
47
48import java.io.File;
49import java.util.HashMap;
50import java.util.Iterator;
51import java.util.NoSuchElementException;
52
53public class ServerTableEntry
54{
55
56    private final static int DE_ACTIVATED = 0;
57    private final static int ACTIVATING   = 1;
58    private final static int ACTIVATED    = 2;
59    private final static int RUNNING      = 3;
60    private final static int HELD_DOWN    = 4;
61
62
63    private String printState()
64    {
65        String str = "UNKNOWN";
66
67        switch (state) {
68        case (DE_ACTIVATED) : str = "DE_ACTIVATED"; break;
69        case (ACTIVATING  ) : str = "ACTIVATING  "; break;
70        case (ACTIVATED   ) : str = "ACTIVATED   "; break;
71        case (RUNNING     ) : str = "RUNNING     "; break;
72        case (HELD_DOWN   ) : str = "HELD_DOWN   "; break;
73        default: break;
74        }
75
76        return str;
77    }
78
79    private final static long waitTime    = 2000;
80    private static final int ActivationRetryMax = 5;
81
82    // state of each entry
83    private int state;
84    private int serverId;
85    private HashMap orbAndPortInfo;
86    private Server serverObj;
87    private ServerDef serverDef;
88    private Process process;
89    private int activateRetryCount=0;
90    private String activationCmd;
91    private ActivationSystemException wrapper ;
92    public String toString()
93    {
94        return "ServerTableEntry[" + "state=" + printState() +
95            " serverId=" + serverId +
96            " activateRetryCount=" + activateRetryCount + "]" ;
97    }
98
99    // get the string needed to make the activation command
100    private static String javaHome, classPath, fileSep, pathSep;
101
102    static {
103        javaHome  = System.getProperty("java.home");
104        classPath = System.getProperty("java.class.path");
105        fileSep   = System.getProperty("file.separator");
106        pathSep   = System.getProperty("path.separator");
107    }
108
109    ServerTableEntry( ActivationSystemException wrapper,
110        int serverId, ServerDef serverDef, int initialPort,
111        String dbDirName, boolean verify, boolean debug )
112    {
113        this.wrapper = wrapper ;
114        this.serverId = serverId;
115        this.serverDef = serverDef;
116        this.debug = debug ;
117        // create a HashMap with capacity 255
118        // Since all methods are synchronized, we don't need any
119        // additional synchronization mechanisms
120        orbAndPortInfo = new HashMap(255);
121
122        activateRetryCount = 0;
123        state = ACTIVATING;
124
125        // compute the activation command
126        activationCmd =
127
128            // add path to the java vm
129            javaHome + fileSep + "bin" + fileSep + "java " +
130
131            // add any arguments to the server Java VM
132            serverDef.serverVmArgs + " " +
133
134            // add ORB properties
135            "-Dioser=" + System.getProperty( "ioser" ) + " " +
136            "-D" + ORBConstants.INITIAL_PORT_PROPERTY   + "=" + initialPort + " " +
137            "-D" + ORBConstants.DB_DIR_PROPERTY         + "=" + dbDirName + " " +
138            "-D" + ORBConstants.ACTIVATED_PROPERTY      + "=true " +
139            "-D" + ORBConstants.SERVER_ID_PROPERTY      + "=" + serverId + " " +
140            "-D" + ORBConstants.SERVER_NAME_PROPERTY    + "=" + serverDef.serverName + " " +
141            // we need to pass in the verify flag, so that the server is not
142            // launched, when we try to validate its definition during registration
143            // into the RepositoryImpl
144
145            (verify ? "-D" + ORBConstants.SERVER_DEF_VERIFY_PROPERTY + "=true ": "") +
146
147            // add classpath to the server
148            "-classpath " + classPath +
149            (serverDef.serverClassPath.equals("") == true ? "" : pathSep) +
150            serverDef.serverClassPath +
151
152            // add server class name and arguments
153            " com.sun.corba.se.impl.activation.ServerMain " + serverDef.serverArgs
154
155            // Add the debug flag, if any
156            + (debug ? " -debug" : "") ;
157
158        if (debug) System.out.println(
159                                      "ServerTableEntry constructed with activation command " +
160                                      activationCmd);
161    }
162
163    /**
164     * Verify whether the server definition is valid.
165     */
166    public int verify()
167    {
168        try {
169
170            if (debug)
171                System.out.println("Server being verified w/" + activationCmd);
172
173            process = Runtime.getRuntime().exec(activationCmd);
174            int result = process.waitFor();
175            if (debug)
176                printDebug( "verify", "returns " + ServerMain.printResult( result ) ) ;
177            return result ;
178        } catch (Exception e) {
179            if (debug)
180                printDebug( "verify", "returns unknown error because of exception " +
181                            e ) ;
182            return ServerMain.UNKNOWN_ERROR;
183        }
184    }
185
186    private void printDebug(String method, String msg)
187    {
188        System.out.println("ServerTableEntry: method  =" + method);
189        System.out.println("ServerTableEntry: server  =" + serverId);
190        System.out.println("ServerTableEntry: state   =" + printState());
191        System.out.println("ServerTableEntry: message =" + msg);
192        System.out.println();
193    }
194
195    synchronized void activate() throws org.omg.CORBA.SystemException
196    {
197        state = ACTIVATED;
198
199        try {
200            if (debug)
201                printDebug("activate", "activating server");
202            process = Runtime.getRuntime().exec(activationCmd);
203        } catch (Exception e) {
204            deActivate();
205            if (debug)
206                printDebug("activate", "throwing premature process exit");
207            throw wrapper.unableToStartProcess() ;
208        }
209    }
210
211    synchronized void register(Server server)
212    {
213        if (state == ACTIVATED) {
214
215            serverObj = server;
216
217            //state = RUNNING;
218            //notifyAll();
219
220            if (debug)
221                printDebug("register", "process registered back");
222
223        } else {
224
225            if (debug)
226                printDebug("register", "throwing premature process exit");
227            throw wrapper.serverNotExpectedToRegister() ;
228        }
229    }
230
231    synchronized void registerPorts( String orbId, EndPointInfo [] endpointList)
232        throws ORBAlreadyRegistered
233    {
234
235        // find if the ORB is already registered, then throw an exception
236        if (orbAndPortInfo.containsKey(orbId)) {
237            throw new ORBAlreadyRegistered(orbId);
238        }
239
240        // store all listener ports and their types
241        int numListenerPorts = endpointList.length;
242        EndPointInfo [] serverListenerPorts = new EndPointInfo[numListenerPorts];
243
244        for (int i = 0; i < numListenerPorts; i++) {
245            serverListenerPorts[i] = new EndPointInfo (endpointList[i].endpointType, endpointList[i].port);
246        if (debug)
247            System.out.println("registering type: " + serverListenerPorts[i].endpointType  +  "  port  " + serverListenerPorts[i].port);
248        }
249
250        // put this set of listener ports in the HashMap associated
251        // with the orbId
252        orbAndPortInfo.put(orbId, serverListenerPorts);
253        if (state == ACTIVATED) {
254            state = RUNNING;
255            notifyAll();
256        }
257        // _REVISIT_, If the state is not equal to ACTIVATED then it is a bug
258        // need to log that error, once the Logging framework is in place
259        // for rip-int.
260        if (debug)
261            printDebug("registerPorts", "process registered Ports");
262    }
263
264    void install()
265    {
266        Server localServerObj = null;
267        synchronized ( this ) {
268            if (state == RUNNING)
269                localServerObj = serverObj;
270            else
271                throw wrapper.serverNotRunning() ;
272        }
273        if (localServerObj != null) {
274            localServerObj.install() ;
275        }
276
277    }
278
279    void uninstall()
280    {
281        Server localServerObj = null;
282        Process localProcess = null;
283
284        synchronized (this) {
285            localServerObj = serverObj;
286            localProcess = process;
287
288            if (state == RUNNING) {
289
290                deActivate();
291
292            } else {
293                throw wrapper.serverNotRunning() ;
294            }
295        }
296        try {
297            if (localServerObj != null) {
298                localServerObj.shutdown(); // shutdown the server
299                localServerObj.uninstall() ; // call the uninstall
300            }
301
302            if (localProcess != null) {
303                localProcess.destroy();
304            }
305        } catch (Exception ex) {
306            // what kind of exception should be thrown
307        }
308    }
309
310    synchronized void holdDown()
311    {
312        state = HELD_DOWN;
313
314        if (debug)
315            printDebug( "holdDown", "server held down" ) ;
316
317        notifyAll();
318    }
319
320    synchronized void deActivate()
321    {
322        state = DE_ACTIVATED;
323
324        if (debug)
325            printDebug( "deActivate", "server deactivated" ) ;
326
327        notifyAll();
328    }
329
330    synchronized void checkProcessHealth( ) {
331        // If the State in the ServerTableEntry is RUNNING and the
332        // Process was shut down abnormally, The method will change the
333        // server state as De-Activated.
334        if( state == RUNNING ) {
335            try {
336                int exitVal = process.exitValue();
337            } catch (IllegalThreadStateException e1) {
338                return;
339            }
340            synchronized ( this ) {
341                // Clear the PortInformation as it is old
342                orbAndPortInfo.clear();
343                // Move the state to De-Activated, So that the next
344                // call to this server will re-activate.
345                deActivate();
346            }
347        }
348    }
349
350    synchronized boolean isValid()
351    {
352        if ((state == ACTIVATING) || (state == HELD_DOWN)) {
353            if (debug)
354                printDebug( "isValid", "returns true" ) ;
355
356            return true;
357        }
358
359        try {
360            int exitVal = process.exitValue();
361        } catch (IllegalThreadStateException e1) {
362            return true;
363        }
364
365        if (state == ACTIVATED) {
366            if (activateRetryCount < ActivationRetryMax) {
367                if (debug)
368                    printDebug("isValid", "reactivating server");
369                activateRetryCount++;
370                activate();
371                return true;
372            }
373
374            if (debug)
375                printDebug("isValid", "holding server down");
376
377            holdDown();
378            return true;
379        }
380
381        deActivate();
382        return false;
383    }
384
385    synchronized ORBPortInfo[] lookup(String endpointType) throws ServerHeldDown
386    {
387        while ((state == ACTIVATING) || (state == ACTIVATED)) {
388            try {
389                wait(waitTime);
390                if (!isValid()) break;
391            } catch(Exception e) {}
392        }
393        ORBPortInfo[] orbAndPortList = null;
394
395        if (state == RUNNING) {
396            orbAndPortList = new ORBPortInfo[orbAndPortInfo.size()];
397            Iterator setORBids = orbAndPortInfo.keySet().iterator();
398
399            try {
400                int numElements = 0;
401                int i;
402                int port;
403                while (setORBids.hasNext()) {
404                    String orbId = (String) setORBids.next();
405                    // get an entry corresponding to orbId
406                    EndPointInfo [] serverListenerPorts = (EndPointInfo []) orbAndPortInfo.get(orbId);
407                    port = -1;
408                    // return the port corresponding to the endpointType
409                    for (i = 0; i < serverListenerPorts.length; i++) {
410                        if (debug)
411                            System.out.println("lookup num-ports " + serverListenerPorts.length + "   " +
412                                serverListenerPorts[i].endpointType + "   " +
413                                serverListenerPorts[i].port );
414                        if ((serverListenerPorts[i].endpointType).equals(endpointType)) {
415                            port = serverListenerPorts[i].port;
416                            break;
417                        }
418                    }
419                    orbAndPortList[numElements] = new ORBPortInfo(orbId, port);
420                    numElements++;
421                }
422            } catch (NoSuchElementException e) {
423                // have everything in the table
424            }
425            return orbAndPortList;
426        }
427
428        if (debug)
429            printDebug("lookup", "throwing server held down error");
430
431        throw new ServerHeldDown( serverId ) ;
432    }
433
434    synchronized EndPointInfo[] lookupForORB(String orbId)
435        throws ServerHeldDown, InvalidORBid
436    {
437        while ((state == ACTIVATING) || (state == ACTIVATED)) {
438            try {
439                wait(waitTime);
440                if (!isValid()) break;
441            } catch(Exception e) {}
442        }
443        EndPointInfo[] portList = null;
444
445        if (state == RUNNING) {
446
447            try {
448
449                // get an entry corresponding to orbId
450                EndPointInfo [] serverListenerPorts = (EndPointInfo []) orbAndPortInfo.get(orbId);
451
452                portList = new EndPointInfo[serverListenerPorts.length];
453                // return the port corresponding to the endpointType
454                for (int i = 0; i < serverListenerPorts.length; i++) {
455                   if (debug)
456                      System.out.println("lookup num-ports " + serverListenerPorts.length + "   "
457                             + serverListenerPorts[i].endpointType + "   " +
458                             serverListenerPorts[i].port );
459                   portList[i] = new EndPointInfo(serverListenerPorts[i].endpointType, serverListenerPorts[i].port);
460                }
461            } catch (NoSuchElementException e) {
462                // no element in HashMap corresponding to ORBid found
463                throw new InvalidORBid();
464            }
465            return portList;
466        }
467
468        if (debug)
469            printDebug("lookup", "throwing server held down error");
470
471        throw new ServerHeldDown( serverId ) ;
472    }
473
474    synchronized String[] getORBList()
475    {
476        String [] orbList = new String[orbAndPortInfo.size()];
477        Iterator setORBids = orbAndPortInfo.keySet().iterator();
478
479        try {
480            int numElements = 0;
481            while (setORBids.hasNext()) {
482                String orbId = (String) setORBids.next();
483                orbList[numElements++] = orbId ;
484            }
485        } catch (NoSuchElementException e) {
486            // have everything in the table
487        }
488        return orbList;
489    }
490
491    int getServerId()
492    {
493        return serverId;
494    }
495
496    boolean isActive()
497    {
498        return (state == RUNNING) || (state == ACTIVATED);
499    }
500
501    synchronized void destroy()
502    {
503
504        Server localServerObj = null;
505        Process localProcess = null;
506
507        synchronized (this) {
508            localServerObj = serverObj;
509            localProcess = process;
510
511            deActivate();
512        }
513
514        try {
515            if (localServerObj != null)
516                localServerObj.shutdown();
517
518            if (debug)
519                printDebug( "destroy", "server shutdown successfully" ) ;
520        } catch (Exception ex) {
521            if (debug)
522                printDebug( "destroy",
523                            "server shutdown threw exception" + ex ) ;
524            // ex.printStackTrace();
525        }
526
527        try {
528            if (localProcess != null)
529                localProcess.destroy();
530
531            if (debug)
532                printDebug( "destroy", "process destroyed successfully" ) ;
533        } catch (Exception ex) {
534            if (debug)
535                printDebug( "destroy",
536                            "process destroy threw exception" + ex ) ;
537
538            // ex.printStackTrace();
539        }
540    }
541
542    private boolean debug = false;
543}
544