Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
  /*
   * JBoss, Home of Professional Open Source.
   * Copyright 2011, Red Hat, Inc., and individual contributors
   * as indicated by the @author tags. See the copyright.txt file in the
   * distribution for a full listing of individual contributors.
   *
   * This is free software; you can redistribute it and/or modify it
   * under the terms of the GNU Lesser General Public License as
   * published by the Free Software Foundation; either version 2.1 of
  * the License, or (at your option) any later version.
  *
  * This software is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  * Lesser General Public License for more details.
  *
  * You should have received a copy of the GNU Lesser General Public
  * License along with this software; if not, write to the Free
  * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
  * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
  */
 
 package org.jboss.as.host.controller;
 
 import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.HOST;
 import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.OP;
 import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.OP_ADDR;
 import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.RUNNING_SERVER;
 import static org.jboss.as.host.controller.HostControllerLogger.ROOT_LOGGER;
 
 import java.util.List;
 import java.util.Map;
 
Represents a managed server.

Author(s):
David M. Lloyd
Kabir Khan
Brian Stansberry
Emanuel Muckenhuber
 
 class ManagedServer {
 
     private static final Logger.Level DEBUG_LEVEL = ..;
     private static final MarshallerFactory MARSHALLER_FACTORY;
     private static final MarshallingConfiguration CONFIG;
 
     static {
          = Marshalling.getMarshallerFactory("river"Marshalling.class.getClassLoader());
 
         final ClassLoader cl = ManagedServer.class.getClassLoader();
         final MarshallingConfiguration config = new MarshallingConfiguration();
         config.setVersion(2);
         config.setClassResolver(new SimpleClassResolver(cl));
          = config;
     }

    
Prefix applied to a server's name to create it's process name.
 
     private static final String SERVER_PROCESS_NAME_PREFIX = "Server:";
 
     static String getServerProcessName(String serverName) {
         return  + serverName;
     }
 
     static boolean isServerProcess(String serverProcessName) {
         return serverProcessName.startsWith();
     }
 
    static String getServerName(String serverProcessName) {
        return serverProcessName.substring(.length());
    }
    private final byte[] authKey;
    private final String serverName;
    private final String serverProcessName;
    private final String hostControllerName;
    private final InetSocketAddress managementSocket;
    private final ManagedServerProxy protocolClient;
    private volatile boolean requiresReload;
    private volatile InternalState requiredState = .;
    private volatile InternalState internalState = .;
    private volatile int operationID = CurrentOperationIdHolder.getCurrentOperationID();
    ManagedServer(final String hostControllerNamefinal String serverNamefinal byte[] authKey,
                  final ProcessControllerClient processControllerClientfinal InetSocketAddress managementSocket,
                  final TransformationTarget transformationTarget) {
        assert hostControllerName  != null : "hostControllerName is null";
        assert serverName  != null : "serverName is null";
        assert processControllerClient != null : "processControllerSlave is null";
        assert managementSocket != null : "managementSocket is null";
        this. = hostControllerName;
        this. = serverName;
        this. = getServerProcessName(serverName);
        this. = processControllerClient;
        this. = managementSocket;
        this. = authKey;
        // Setup the proxy controller
        final PathElement serverPath = PathElement.pathElement(serverName);
        final PathAddress address = ..append(PathElement.pathElement(hostControllerName), serverPath);
        this. = new ManagedServerProxy(this);
        this. = TransformingProxyController.Factory.create(,
                Transformers.Factory.create(transformationTarget), address.true);
    }

    
Get the process auth key.

Returns:
the auth key
    byte[] getAuthKey() {
        return ;
    }

    
Get the server name.

Returns:
the server name
    public String getServerName() {
        return ;
    }

    
Get the transforming proxy controller instance.

Returns:
the proxy controller
        return ;
    }

    
Determine the current state the server is in.

Returns:
the server status
    public ServerStatus getState() {
        final InternalState requiredState = this.;
        final InternalState state = ;
        if(requiredState == .) {
            return .;
        }
        switch (state) {
            case :
                return .;
            case :
                return  .;
            default: {
                if(requiredState == .) {
                    return .;
                } else {
                    return .;
                }
            }
        }
    }
    protected boolean isRequiresReload() {
        return ;
    }

    
Require a reload on the the next reconnect.
    protected void requireReload() {
         = true;
    }

    
Reload a managed server.

Parameters:
permit the controller permit
Returns:
whether the state was changed successfully or not
    protected synchronized boolean reload(int permit) {
    }

    
Start a managed server.

Parameters:
factory the boot command factory
    protected synchronized void start(final ManagedServerBootCmdFactory factory) {
        final InternalState required = this.;
        // Ignore if the server is already started
        if(required == .) {
            return;
        }
        // In case the server failed to start, try to start it again
        if(required != .) {
            final InternalState current = this.;
            if(current != required) {
                // TODO this perhaps should wait?
                throw new IllegalStateException();
            }
        }
         = CurrentOperationIdHolder.getCurrentOperationID();
         = factory.createConfiguration();
        transition();
    }

    
Stop a managed server.
    protected synchronized void stop() {
        final InternalState required = this.;
        if(required != .) {
            this. = .;
            .stoppingServer();
            // Transition, but don't wait for async notifications to complete
            transition(false);
        }
    }
    protected synchronized void destroy() {
        final InternalState required = this.;
        if(required == .) {
            if( != .) {
                try {
                    .destroyProcess();
                } catch (IOException e) {
                    .logf(DEBUG_LEVEL, e"failed to send destroy_process message to %s");
                }
            }
        } else {
            stop();
        }
    }
    protected synchronized void kill() {
        final InternalState required = this.;
        if(required == .) {
            if( != .) {
                try {
                    .killProcess();
                } catch (IOException e) {
                    .logf(DEBUG_LEVEL, e"failed to send kill_process message to %s");
                }
            }
        } else {
            stop();
        }
    }

    
Try to reconnect to a started server.
    protected synchronized void reconnectServerProcess(final ManagedServerBootCmdFactory factory) {
        if(this. != .) {
            this. = factory;
            this. = .;
            .reconnectingServer();
        }
    }

    
On host controller reload, remove a not running server registered in the process controller declared as down.
    protected synchronized void removeServerProcess() {
        this. = .;
    }

    
On host controller reload, remove a not running server registered in the process controller declared as stopping.
    protected synchronized void setServerProcessStopping() {
        this. = .;
    }

    
Await a state.

Parameters:
expected the expected state
Returns:
true if the state was reached, false otherwise
    protected boolean awaitState(final InternalState expected) {
        synchronized (this) {
            final InternalState initialRequired = this.;
            for(;;) {
                final InternalState required = this.;
                // Stop in case the server failed to reach the state
                if(required == .) {
                    return false;
                // Stop in case the required state changed
                } else if (initialRequired != required) {
                    return false;
                }
                final InternalState current = this.;
                if(expected == current) {
                    return true;
                }
                try {
                    wait();
                } catch(InterruptedException e) {
                    Thread.currentThread().interrupt();
                    return false;
                }
            }
        }
    }

    
Notification that the process was added
    protected void processAdded() {
    }

    
Notification that the process was started.
    protected void processStarted() {
    }
    protected synchronized TransactionalProtocolClient channelRegistered(final ManagementChannelHandler channelAssociation) {
        final InternalState current = this.;
        // Create the remote controller client
        final TransactionalProtocolClient remoteClient = TransactionalProtocolHandlers.createClient(channelAssociation);
        if      (current == .) {
            internalSetState(new TransitionTask() {
                @Override
                public boolean execute(ManagedServer serverthrows Exception {
                    // Update the current remote connection
                    .connected(remoteClient);
                    // clear reload required state
                     = false;
                    return true;
                }
        } else {
            internalSetState(new TransitionTask() {
                @Override
                public boolean execute(final ManagedServer serverthrows Exception {
                    // Update the current remote connection
                    .connected(remoteClient);
                    return true;
                }
            // TODO we just check that we are in the correct state, perhaps introduce a new state
        }
        return remoteClient;
    }
    protected synchronized void serverStarted(final TransitionTask task) {
    }
    protected synchronized void serverStartFailed() {
    }

    
Unregister the mgmt channel.

Parameters:
old the proxy controller to unregister
shuttingDown whether the server inventory is shutting down
Returns:
whether the registration can be removed from the domain-controller
    protected synchronized boolean callbackUnregistered(final TransactionalProtocolClient oldfinal boolean shuttingDown) {
        // Disconnect the remote connection
        .disconnected(old);
        // If the connection dropped without us stopping the process ask for reconnection
        if(! shuttingDown &&  == .) {
            final InternalState state = ;
            if(state == .
                    || state == .
                    || state == .) {
                // In case it stopped we don't reconnect
                return true;
            }
            // In case we are reloading, it will reconnect automatically
            if (state == .) {
                return true;
            }
            try {
                .logf(DEBUG_LEVEL, "trying to reconnect to %s current-state (%s) required-state (%s)"state);
                internalSetState(new ReconnectTask(), state.);
            } catch (Exception e) {
                .logf(DEBUG_LEVEL, e"failed to send reconnect task");
            }
            return false;
        } else {
            return true;
        }
    }

    
Notification that the server process finished.
    protected synchronized void processFinished() {
        final InternalState required = this.;
        final InternalState state = this.;
        // If the server was not stopped
        if(required == . && state == .) {
        } else {
            this. = .;
            internalSetState(nullstate.);
        }
    }

    
Notification that the process got removed from the process controller.
    protected void processRemoved() {
    }
    private void transition() {
        transition(true);
    }
    private synchronized void transition(boolean checkAsync) {
        final InternalState required = this.;
        final InternalState current = this.;
        // Check if we are waiting for a notification from the server
        if(checkAsync && current.isAsync()) {
            return;
        }
        final InternalState next = nextState(currentrequired);
        if(next != null) {
            final TransitionTask task = getTransitionTask(next);
            internalSetState(taskcurrentnext);
        }
    }

    
Notification that a state transition failed.

Parameters:
state the failed transition
    synchronized void transitionFailed(final InternalState state) {
        final InternalState current = this.;
        if(state == current) {
            // Revert transition and mark as failed
            switch (current) {
                case :
                    this. = .;
                    break;
                case :
                    break;
                case :
                    this. = .;
                    break;
                case :
                case :
                    this. = .;
                    break;
            }
            this. = .;
            notifyAll();
        }
    }

    
Finish a state transition from a notification.

Parameters:
current
next
    private synchronized void finishTransition(final InternalState currentfinal InternalState next) {
        internalSetState(getTransitionTask(next), currentnext);
        transition();
    }
    private boolean internalSetState(final TransitionTask taskfinal InternalState currentfinal InternalState next) {
        assert Thread.holdsLock(this); // Call under lock
        final InternalState internalState = this.;
        .logf(DEBUG_LEVEL, "changing server state (%s) from %s to %s"currentnext);
        if(internalState == current) {
            try {
                if(task != null) {
                    if(! task.execute(this)) {
                        return true// Not a failure condition
                    }
                }
                this. = next;
                return true;
            } catch (final Exception e) {
                .logf(DEBUG_LEVEL, e"transition (%s > %s) failed for server \"%s\""currentnext);
                transitionFailed(current);
            } finally {
                notifyAll();
            }
        }
        return false;
    }
    private TransitionTask getTransitionTask(final InternalState next) {
        switch (next) {
            case : {
                return new ProcessAddTask();
            } case : {
                return new ProcessStartTask();
            } case : {
                return new SendStdInTask();
            } case : {
                return new ServerStartedTask();
            } case : {
                return new ServerStopTask();
            } case : {
                return new ProcessRemoveTask();
            } default: {
                return null;
            }
        }
    }
    private static InternalState nextState(final InternalState statefinal InternalState required) {
        switch (state) {
            case : {
                if(required == .) {
                    return .;
                }
                break;
            } case : {
                if(required == .) {
                    return .;
                }
                break;
            } case : {
                if(required == .) {
                    return .;
                } else ifrequired == .) {
                    return .;
                }
                break;
            } case : {
                if(required == .) {
                    return .;
                }
                break;
            } case : {
                if(required == .) {
                    return .;
                } else ifrequired == .) {
                    return .;
                }
                break;
            } case : {
                if(required == .) {
                    return .;
                } else ifrequired == .) {
                    return .;
                }
                break;
            } case : {
                if(required == .) {
                    return .;
                } else ifrequired == .) {
                    return .;
                }
                break;
            } case : {
                if(required == .) {
                    return .;
                }
                break;
            } case : {
                if (required == .) {
                    return .;
                } else if (required == .) {
                    return .;
                }
                break;
            } case : {
                if(required == .) {
                    return .;
                }
                break;
            } case : {
                if(required == .) {
                    return .;
                } else ifrequired == .) {
                    return .;
                }
                break;
            } case : {
                if(required == .) {
                    return .;
                }
                break;
            } default: {
                return null;
            }
        }
        return null;
    }
    static enum InternalState {
        STOPPED,
        PROCESS_ADDING(true),
        PROCESS_ADDED,
        PROCESS_STARTING(true),
        PROCESS_STARTED,
        SEND_STDIN(true),
        SERVER_STARTING(true),
        SERVER_STARTED,
        RELOADING(true),
        PROCESS_STOPPING(true),
        PROCESS_STOPPED,
        PROCESS_REMOVING(true),
        FAILED,
        ;

        
State transition creates an async task.
        private final boolean async;
        InternalState() {
            this(false);
        }
        InternalState(boolean async) {
            this. = async;
        }
        public boolean isAsync() {
            return ;
        }
    }
    interface TransitionTask {
        boolean execute(ManagedServer serverthrows Exception;
    }
    private class ProcessAddTask implements TransitionTask {
        @Override
        public boolean execute(ManagedServer serverthrows Exception {
            assert Thread.holdsLock(ManagedServer.this); // Call under lock
            final List<Stringcommand = .getServerLaunchCommand();
            final Map<StringStringenv = .getServerLaunchEnvironment();
            final HostControllerEnvironment environment = .getHostControllerEnvironment();
            // Add the process to the process controller
            .addProcess(command.toArray(new String[command.size()]), environment.getHomeDir().getAbsolutePath(), env);
            return true;
        }
    }
    private class ProcessRemoveTask implements TransitionTask {
        @Override
        public boolean execute(ManagedServer serverthrows Exception {
            assert Thread.holdsLock(ManagedServer.this); // Call under lock
            // Remove process
            return true;
        }
    }
    private class ProcessStartTask implements TransitionTask {
        @Override
        public boolean execute(ManagedServer serverthrows Exception {
            assert Thread.holdsLock(ManagedServer.this); // Call under lock
            // Start the process
            return true;
        }
    }
    private class SendStdInTask implements TransitionTask {
        @Override
        public boolean execute(ManagedServer serverthrows Exception {
            assert Thread.holdsLock(ManagedServer.this); // Call under lock
            // Get the standalone boot updates
            final List<ModelNodebootUpdates = Collections.emptyList(); // bootConfiguration.getBootUpdates();
            final Map<StringStringlaunchProperties = parseLaunchProperties(.getServerLaunchCommand());
            final boolean useSubsystemEndpoint = .isManagementSubsystemEndpoint();
            final ModelNode endpointConfig = .getSubsystemEndpointConfiguration();
            // Send std.in
            final ServiceActivator hostControllerCommActivator = DomainServerCommunicationServices.create(endpointConfiguseSubsystemEndpoint);
            final ServerStartTask startTask = new ServerStartTask(, 0, , Collections.<ServiceActivator>singletonList(hostControllerCommActivator), bootUpdateslaunchProperties);
            final Marshaller marshaller = .createMarshaller();
            final OutputStream os = .sendStdin();
            marshaller.start(Marshalling.createByteOutput(os));
            marshaller.writeObject(startTask);
            marshaller.finish();
            marshaller.close();
            os.close();
            return true;
        }
    }
    private class ServerStartedTask implements TransitionTask {
        @Override
        public boolean execute(ManagedServer serverthrows Exception {
            return true;
        }
    }
    private class ServerStopTask implements TransitionTask {
        @Override
        public boolean execute(ManagedServer serverthrows Exception {
            assert Thread.holdsLock(ManagedServer.this); // Call under lock
            // Stop process
            return true;
        }
    }
    private class ReconnectTask implements TransitionTask {
        @Override
        public boolean execute(ManagedServer serverthrows Exception {
            assert Thread.holdsLock(ManagedServer.this); // Call under lock
            // Reconnect
            final String hostName = .getHostString();
            final int port = .getPort();
            return true;
        }
    }
    private class ReloadTask implements TransitionTask {
        private final int permit;
        private ReloadTask(int permit) {
            this. = permit;
        }
        @Override
        public boolean execute(ManagedServer serverthrows Exception {
            final ModelNode operation = new ModelNode();
            operation.get().set("reload");
            operation.get().setEmptyList();
            operation.get("operation-id").set();
            try {
                final TransactionalProtocolClient.PreparedOperation<?> prepared = TransactionalProtocolHandlers.executeBlocking(operation);
                if (prepared.isFailed()) {
                    return false;
                }
                prepared.commit(); // Just commit and discard the result
            } catch (IOException ignore) {
                //
            }
            return true;
        }
    }
    private static Map<StringStringparseLaunchProperties(final List<Stringcommands) {
        final Map<StringStringresult = new LinkedHashMap<StringString>();
        for (String cmd : commands) {
            if (cmd.startsWith("-D")) {
                final String[] parts = cmd.substring(2).split("=");
                if (parts.length == 2) {
                    result.put(parts[0], parts[1]);
                } else if (parts.length == 1) {
                    result.put(parts[0], "true");
                }
            }
        }
        return result;
    }
New to GrepCode? Check out our FAQ X