Activation.java revision 2362
2362N/A * Copyright (c) 1997, 2006, Oracle and/or its affiliates. All rights reserved. 0N/A * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 0N/A * This code is free software; you can redistribute it and/or modify it 0N/A * under the terms of the GNU General Public License version 2 only, as 2362N/A * published by the Free Software Foundation. Oracle designates this 0N/A * particular file as subject to the "Classpath" exception as provided 2362N/A * by Oracle in the LICENSE file that accompanied this code. 0N/A * This code is distributed in the hope that it will be useful, but WITHOUT 0N/A * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 0N/A * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 0N/A * version 2 for more details (a copy is included in the LICENSE file that 0N/A * accompanied this code). 0N/A * You should have received a copy of the GNU General Public License version 0N/A * 2 along with this work; if not, write to the Free Software Foundation, 0N/A * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 2362N/A * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 2362N/A * or visit www.oracle.com if you need additional information or have any 0N/A * The Activator facilitates remote object activation. A "faulting" 0N/A * remote reference calls the activator's <code>activate</code> method 0N/A * to obtain a "live" reference to a activatable remote object. Upon 0N/A * receiving a request for activation, the activator looks up the 0N/A * activation descriptor for the activation identifier, id, determines 0N/A * the group in which the object should be activated and invokes the 0N/A * activate method on the object's activation group (described by the 0N/A * remote interface <code>ActivationInstantiator</code>). The 0N/A * activator initiates the execution of activation groups as 0N/A * necessary. For example, if an activation group for a specific group 0N/A * identifier is not already executing, the activator will spawn a 0N/A * child process for the activation group. <p> 0N/A * The activator is responsible for monitoring and detecting when 0N/A * activation groups fail so that it can remove stale remote references 0N/A * from its internal tables. <p> 0N/A * @author Ann Wollrath 0N/A /** indicate compatibility with JDK 1.2 version of class */ 0N/A /** exec policy object */ 0N/A /** maps activation id to its respective group id */ 0N/A /** maps group id to its GroupEntry groups */ 0N/A /** number of simultaneous group exec's */ 0N/A /** counter for numbering groups */ 0N/A /** reliable log to hold descriptor table */ 0N/A /** number of updates since last snapshot */ 0N/A /** the java command */ 0N/A // accessed by GroupEntry 0N/A /** timeout on wait for child process to be created or destroyed */ 0N/A getInt(
"sun.rmi.activation.groupTimeout",
60000);
0N/A /** take snapshot after this many updates */ 0N/A getInt(
"sun.rmi.activation.snapshotInterval",
200);
0N/A /** timeout on wait for child process to be created */ 0N/A getInt(
"sun.rmi.activation.execTimeout",
30000);
0N/A // this should be a *private* method since it is privileged 0N/A * Create an uninitialized instance of Activation that can be 0N/A * populated with log data. This is only called when the initial 0N/A * snapshot is taken during the first incarnation of rmid. 0N/A * Recover activation state from the reliable log and initialize 0N/A * activation services. 0N/A * Initialize the Activation instantiation; start activation 0N/A // all the remote methods briefly synchronize on startupLock 0N/A // (via checkShutdown) to make sure they don't happen in the 0N/A // middle of this block. This block must not cause any such 0N/A // incoming remote calls to happen, or deadlock would result! 0N/A * Returns the activation system stub if the specified name 0N/A * matches the activation system's class name, otherwise 0N/A * returns the result of invoking super.lookup with the specified 0N/A "binding ActivationSystem is disallowed");
0N/A "unbinding ActivationSystem is disallowed");
0N/A "binding ActivationSystem is disallowed");
0N/A // Because ActivatorImpl has a fixed ObjID, it can be 0N/A // called by clients holding stale remote references. Each of 0N/A // its remote methods, then, must check startupLock (calling 0N/A // checkShutdown() is easiest). 0N/A * Construct a new Activator on a specified port. 0N/A /* Server ref must be created and assigned before remote object 0N/A * 'this' can be exported. 0N/A // Because ActivationSystemImpl has a fixed ObjID, it can be 0N/A // called by clients holding stale remote references. Each of 0N/A // its remote methods, then, must check startupLock (calling 0N/A // checkShutdown() is easiest). 0N/A /* Server ref must be created and assigned before remote object 0N/A * 'this' can be exported. 0N/A // table insertion must take place before log update 0N/A // remove entry before unregister so state is updated before 0N/A "ActivationDesc contains wrong group");
0N/A "ActivationSystem.setActivationGroupDesc");
0N/A (
"ActivationSystem.getActivationGroupDesc");
0N/A * Shutdown the activation system. Destroys all groups spawned by 0N/A * the activation daemon and exits the activation daemon. 0N/A // if the startup critical section is running, wait until it 0N/A "activation system shutting down");
0N/A * Thread to shutdown rmid. 0N/A super(
"rmid Shutdown");
0N/A * Unexport activation system services 0N/A // destroy all child processes (groups) 0N/A * Unexport monitor safely since all processes are destroyed. 0N/A * Close log file, fix for 4243264: rmid shutdown thread 0N/A * interferes with remote calls in progress. Make sure 0N/A * the log file is only closed when it is impossible for 0N/A * its closure to interfere with any pending remote calls. 0N/A * We close the log when all objects in the rmid VM are 0N/A * Now exit... A System.exit should only be done if 0N/A * the RMI activation system daemon was started up 0N/A * by the main method below (in which should always 0N/A * be the case since the Activation contructor is private). 0N/A /** Thread to destroy children in the event of abnormal termination. */ 0N/A super(
"rmid ShutdownHook");
0N/A // destroy all child processes (groups) quickly 0N/A * Returns the groupID for a given id of an object in the group. 0N/A * Throws UnknownObjectException if the object is not registered. 0N/A * Returns the group entry for the group id. Throws 0N/A * UnknownGroupException if the group is not registered. 0N/A * Returns the group entry for the object's id. Throws 0N/A * UnknownObjectException if the object is not registered or the 0N/A * object's group is not registered. 0N/A * Container for group information: group's descriptor, group's 0N/A * instantiator, flag to indicate pending group creation, and 0N/A * table of the group's actived objects. 0N/A * WARNING: GroupEntry objects should not be written into log file 0N/A * updates. GroupEntrys are inner classes of Activation and they 0N/A * can not be serialized independent of this class. If the 0N/A * complete Activation system is written out as a log update, the 0N/A * point of having updates is nullified. 0N/A /** indicate compatibility with JDK 1.2 version of class */ 0N/A synchronized (
this) {
0N/A * Clone the restartSet so the set does not have to be locked 0N/A * during iteration. Locking the restartSet could cause 0N/A * deadlock if an object we are restarting caused another 0N/A * object in this group to be activated. 0N/A // table insertion must take place before log update 0N/A // table insertion must take place before log update 0N/A // removal should be recorded before log update 0N/A // restart information should be recorded before log update 0N/A // state update should occur before log update 0N/A // REMIND: print message that group did not terminate? 0N/A // no synchronization to avoid delay wrt getInstantiator 0N/A * Attempt to activate object and reattempt (several times) 0N/A * if activation fails due to communication problems. 0N/A // look up object to activate 0N/A synchronized (
this) {
0N/A // if not forcing activation, return cached stub 0N/A // REMIND: wait some here before continuing? 0N/A // group has failed or is inactive; mark inactive 0N/A * signal that group activation failed, nested exception 0N/A * specifies what exception occurred when the group did not 0N/A * Returns the instantiator for the group specified by id and 0N/A * entry. If the group is currently inactive, exec some 0N/A * bootstrap code to create the group. 0N/A // handle child I/O streams before writing to child 0N/A "unable to create activation group", e);
0N/A "activation group unregistered" :
0N/A "timeout creating child process"));
0N/A * Waits for process termination and then restarts services. 0N/A * Wait for the group to crash or exit. 0N/A * Since the group crashed, we should 0N/A * reset the entry before activating objects 0N/A * Activate those objects that require restarting 0N/A * Marks this thread as one that is no longer needed. 0N/A * If the thread is in a state in which it can be interrupted, 0N/A * then the thread is interrupted. 0N/A * Marks this thread as no longer needing to restart objects. 0N/A // argv is the literal command to exec 0N/A // Group-specific command options 0N/A // Properties become -D parameters 0N/A /* Note on quoting: it would be wrong 0N/A * here, since argv will be passed to 0N/A * Runtime.exec, which should not parse 0N/A * arguments or split on whitespace. 0N/A /* Finally, rmid-global command options (e.g. -C options) 0N/A * Check exec command using execPolicy object 0N/A /** descriptor for object */ 0N/A /** the stub (if active) */ 0N/A * stub could be set to null by a group reset, so return 0N/A * the newstub here to prevent returning null. 0N/A * Add a record to the activation log. If the number of updates 0N/A * passes a predetermined threshold, record a snapshot. 0N/A // shutdown activation system because snapshot failed 0N/A // warn the client of the original update problem 0N/A * Handler for the log that knows how to take the initial snapshot 0N/A * and apply an update (a LogRecord) to the current state. 0N/A * Return an empty Activation object. Log will update 0N/A * this object with recovered state. 0N/A * Abstract class for all log records. The subclass contains 0N/A * specific update information and implements the apply method 0N/A * that applys the update information contained in the record 0N/A * to the current state. 0N/A /** indicate compatibility with JDK 1.2 version of class */ 0N/A * Log record for registering an object. 0N/A /** indicate compatibility with JDK 1.2 version of class */ 0N/A "LogRegisterObject"));
0N/A * Log record for unregistering an object. 0N/A /** indicate compatibility with JDK 1.2 version of class */ 0N/A "LogUnregisterObject"));
0N/A * Log record for registering a group. 0N/A /** indicate compatibility with JDK 1.2 version of class */ 0N/A // modify state directly; cant ask a nonexistent GroupEntry 0N/A // to register itself. 0N/A * Log record for udpating an activation desc 0N/A /** indicate compatibility with JDK 1.2 version of class */ 0N/A * Log record for unregistering a group. 0N/A /** indicate compatibility with JDK 1.2 version of class */ 0N/A "LogUpdateGroupDesc"));
0N/A * Log record for unregistering a group. 0N/A /** indicate compatibility with JDK 1.2 version of class */ 0N/A "LogUnregisterGroup"));
0N/A * Log record for an active group incarnation 0N/A /** indicate compatibility with JDK 1.2 version of class */ 0N/A "LogGroupIncarnation"));
0N/A * Initialize command to exec a default group. 0N/A * The default policy for checking a command before it is executed 0N/A * makes sure the appropriate com.sun.rmi.rmid.ExecPermission and 0N/A * set of com.sun.rmi.rmid.ExecOptionPermissions have been granted. 0N/A * Check properties overrides. 0N/A * Check group class name (allow nothing but the default), 0N/A * code location (must be null), and data (must be null). 0N/A "access denied (custom group implementation not allowed)");
0N/A * If group descriptor has a command environment, check 0N/A * command and options. 0N/A * Prints warning message if installed Policy is the default Policy 0N/A * implementation and globally granted permissions do not include 0N/A * The approach used here is taken from the similar method 0N/A * getLoaderAccessControlContext() in the class 0N/A * sun.rmi.server.LoaderHandler. 0N/A // obtain permissions granted to all code in current policy 0N/A * Main program to start the activation system. <br> 0N/A * The usage is as follows: rmid [-port num] [-log dir]. 0N/A // Create and install the security manager if one is not installed 0N/A * If rmid has an inherited channel (meaning that it was 0N/A * launched from inetd), set the server socket factory to 0N/A * return the inherited server socket. 0N/A * Redirect System.err output to a file. 0N/A "rmid.inherited.channel.info") +
0N/A * Determine class name for activation exec policy (if any). 0N/A * Initialize method for activation exec policy. 0N/A * Fix for 4173960: Create and initialize activation using 0N/A * a static method, startActivation, which will build the 0N/A * Activation state in two ways: if when rmid is run, no 0N/A * log file is found, the ActLogHandler.recover(...) 0N/A * method will create a new Activation instance. 0N/A * Alternatively, if a logfile is available, a serialized 0N/A * instance of activation will be read from the log's 0N/A * snapshot file. Log updates will be applied to this 0N/A * Activation object until rmid's state has been fully 0N/A * recovered. In either case, only one instance of 0N/A * Activation is created. 0N/A // prevent activator from exiting 0N/A * Retrieves text resources from the locale-specific properties file. 0N/A "sun.rmi.server.resources.rmid");
0N/A // throwing an Error is a bit extreme, methinks 0N/A return (
"[missing resource file: " +
key +
"]");
0N/A return (
"[missing resource: " +
key +
"]");
0N/A * Dijkstra semaphore operations to limit the number of subprocesses 0N/A * rmid attempts to make at once. 0N/A * Acquire the group semaphore and return a group name. Each 0N/A * Pstartgroup must be followed by a Vstartgroup. The calling thread 0N/A * will wait until there are fewer than <code>N</code> other threads 0N/A * holding the group semaphore. The calling thread will then acquire 0N/A * the semaphore and return. 0N/A // Wait until positive, then decrement. 0N/A * Release the group semaphore. Every P operation must be 0N/A * followed by a V operation. This may cause another thread to 0N/A * wake up and return from its P operation. 0N/A // Increment and notify a waiter (not necessarily FIFO). 0N/A * A server socket factory to use when rmid is launched via 'inetd' 0N/A * with 'wait' status. This socket factory's 'createServerSocket' 0N/A * method returns the server socket specified during construction that 0N/A * is specialized to delay accepting requests until the 0N/A * 'initDone' flag is 'true'. The server socket supplied to 0N/A * the constructor should be the server socket obtained from the 0N/A * ServerSocketChannel returned from the 'System.inheritedChannel' 0N/A * Constructs an 'ActivationServerSocketFactory' with the specified 0N/A * Returns the server socket specified during construction wrapped 0N/A * in a 'DelayedAcceptServerSocket'. 0N/A * A server socket that delegates all public methods to the underlying 0N/A * server socket specified at construction. The accept method is 0N/A * overridden to delay calling accept on the underlying server socket 0N/A * until the 'initDone' flag is 'true'. 0N/A * Delays calling accept on the underlying server socket until the 0N/A * remote service is bound in the registry. 0N/A * PipeWriter plugs together two pairs of input and output streams by 0N/A * providing readers for input streams and writing through to 0N/A * appropriate output streams. Both output streams are annotated on a 0N/A * @author Laird Dornin, much code borrowed from Peter Jones, Ken 0N/A * Arnold and Ann Wollrath. 0N/A /** stream used for buffering lines */ 0N/A /** count since last separator */ 0N/A /** current chunk of input being compared to lineSeparator.*/ 0N/A * Create a new PipeWriter object. All methods of PipeWriter, 0N/A * except plugTogetherPair, are only accesible to PipeWriter 0N/A * itself. Synchronization is unnecessary on functions that will 0N/A * only be used internally in PipeWriter. 0N/A * @param in input stream from which pipe input flows 0N/A * @param out output stream to which log messages will be sent 0N/A * @param dest String which tags output stream as 'out' or 'err' 0N/A * @param nExecs number of execed processes, Activation groups. 0N/A * Create a thread to listen and read from input stream, in. buffer 0N/A * the data that is read until a marker which equals lineSeparator 0N/A * is read. Once such a string has been discovered; write out an 0N/A * annotation string followed by the buffered data and a line 0N/A /* read bytes till there are no more. */ 0N/A /* flush internal buffer... may not have ended on a line 0N/A * separator, we also need a last annotation if 0N/A * something was left. 0N/A // to make output nicer 0N/A * Write a subarray of bytes. Pass each through write byte method. 0N/A for (
int i =
0; i <
len; ++ i) {
0N/A * Write a byte of data to the stream. If we have not matched a 0N/A * line separator string, then the byte is appended to the internal 0N/A * buffer. If we have matched a line separator, then the currently 0N/A * buffered line is sent to the output writer with a prepended 0N/A * annotation string. 0N/A /* shift current to the left */ 0N/A /* enough characters for a separator? */ 0N/A /* write prefix through to underlying byte stream */ 0N/A (
"PipeWriter: IO Exception when"+
0N/A " writing to output stream.");
0N/A * Create an annotation string to be printed out after 0N/A * a new line and end of stream. 0N/A /* construct prefix for log messages: 0N/A /* ... print pair # ... */ 0N/A * Allow plugging together two pipes at a time, to associate 0N/A * output from an execed process. This is the only publicly 0N/A * accessible method of this object; this helps ensure that 0N/A * synchronization will not be an issue in the annotation 0N/A * @param in input stream from which pipe input comes 0N/A * @param out output stream to which log messages will be sent 0N/A * @param in1 input stream from which pipe input comes 0N/A * @param out1 output stream to which log messages will be sent 0N/A /* start RMI threads to read output from child process */