Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
  /*
   * JBoss, Home of Professional Open Source.
   * Copyright 2012, 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.mgmt;
 
 import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.EXTENSION;
 import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.FAILED;
 import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.FAILURE_DESCRIPTION;
 import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.OUTCOME;
 import static org.jboss.as.host.controller.HostControllerLogger.DOMAIN_LOGGER;
 import static org.jboss.as.process.protocol.ProtocolUtils.expectHeader;
 
 
Handler responsible for the host-controller registration process. This may involve assembling the correct ManagementRequestHandlerFactory based on the version of the host-controller registering.

Author(s):
Emanuel Muckenhuber
 
 
     private static final ModelNode READ_DOMAIN_MODEL = new ModelNode();
     static {
         .protect();
     }
 
     private final ManagementChannelHandler handler;
     private final OperationExecutor operationExecutor;
     private final DomainController domainController;
     private final Executor registrations;
 
    public HostControllerRegistrationHandler(ManagementChannelHandler handlerDomainController domainControllerOperationExecutor operationExecutorExecutor registrationsDomainControllerRuntimeIgnoreTransformationRegistry runtimeIgnoreTransformationRegistry) {
        this. = handler;
        this. = operationExecutor;
        this. = domainController;
        this. = registrations;
        this. = runtimeIgnoreTransformationRegistry;
    }
    @Override
    public ManagementRequestHandler<?, ?> resolveHandler(final RequestHandlerChain handlersfinal ManagementRequestHeader header) {
        if (header.getVersion() != 1) {
            // Send subject
        }
        final byte operationId = header.getOperationId();
        switch (operationId) {
                // Start the registration process
                context.activeOperation = handlers.registerActiveOperation(header.getBatchId(), contextcontext);
                return new InitiateRegistrationHandler();
            }
                // Start the fetch the domain model process
                final RegistrationContext context = new RegistrationContext(.getExtensionRegistry().getTransformerRegistry());
                context.activeOperation = handlers.registerActiveOperation(header.getBatchId(), contextcontext);
                return new InitiateRegistrationHandler();
            }
                // register the subsystem versions
                return new RegisterSubsystemVersionsHandler();
                // Complete the registration process
                return new CompleteRegistrationHandler();
        }
        return handlers.resolveNext();
    }

    
wrapper to the DomainController and the underlying ModelController to execute a OperationStepHandler implementation directly, bypassing normal domain coordination layer.
    public interface OperationExecutor {

        
Execute the operation.

Parameters:
operation operation
handler the message handler
control the transaction control
attachments the operation attachments
step the step to be executed
Returns:
the result
        ModelNode execute(ModelNode operationOperationMessageHandler handlerModelController.OperationTransactionControl controlOperationAttachments attachmentsOperationStepHandler step);

        
Join an existing operation, which is currently being executed.

Parameters:
operation the operation
handler the message handler
control the transaction control
attachments the operation attachments
step the step to be executed
permit the operation permit to join
Returns:
the result
    }
        @Override
        public void handleRequest(final DataInput inputfinal ActiveOperation.ResultHandler<VoidresultHandlerfinal ManagementRequestContext<RegistrationContextcontextthrows IOException {
            expectHeader(input.);
            final String hostName = input.readUTF();
            final ModelNode hostInfo = new ModelNode();
            hostInfo.readExternal(input);
            final RegistrationContext registration = context.getAttachment();
            registration.initialize(hostNamehostInfocontext);
            if (.getCurrentRunningMode() == .) {
                return;
            }
            if (!.getLocalHostInfo().isMasterDomainController()) {
                return;
            }
            // Read the domain model async, this will block until the registration process is complete
            context.executeAsync(new ManagementRequestContext.AsyncTask<RegistrationContext>() {
                @Override
                public void execute(ManagementRequestContext<RegistrationContextcontextthrows Exception {
                    registration.processRegistration();
                }
            }, );
        }
    }
        @Override
        public void handleRequest(DataInput inputActiveOperation.ResultHandler<VoidresultHandlerManagementRequestContext<RegistrationContextcontextthrows IOException {
            final byte status = input.readByte();
            final ModelNode subsystems = new ModelNode();
            subsystems.readExternal(input);
            final RegistrationContext registration = context.getAttachment();
            if(status == .) {
                registration.setSubsystems(subsystemscontext);
            } else {
                registration.setSubsystems(nullcontext);
            }
        }
    }

    
Handler responsible for completing the registration request.
        @Override
        public void handleRequest(final DataInput inputfinal ActiveOperation.ResultHandler<VoidresultHandlerfinal ManagementRequestContext<RegistrationContextcontextthrows IOException {
            final byte status = input.readByte();
            final String message = input.readUTF(); // Perhaps use message when the host failed
            final RegistrationContext registration = context.getAttachment();
            // Complete the registration
            registration.completeRegistration(contextstatus == .);
        }
    }
        private final TransformerRegistry transformerRegistry;
        private final RegistrationContext registrationContext;
        protected HostRegistrationStepHandler(final TransformerRegistry transformerRegistryfinal RegistrationContext registrationContextfinal DomainControllerRuntimeIgnoreTransformationRegistry runtimeIgnoreTransformationRegistry) {
            this. = registrationContext;
            this. = transformerRegistry;
            this. = runtimeIgnoreTransformationRegistry;
        }
        @Override
        public void execute(final OperationContext contextfinal ModelNode operationthrows OperationFailedException {
            // First lock the domain controller
            context.acquireControllerLock();
            // Check with the controller lock held
                final String failureDescription = ..slaveAlreadyRegistered(.);
                .failed(..failureDescription);
                context.getFailureDescription().set(failureDescription);
                context.stepCompleted();
                return;
            }
            // Read the extensions (with recursive true, otherwise the entries are runtime=true - which are going to be ignored for transformation)
            final Resource root = context.readResourceFromRoot(..append(PathElement.pathElement()), true);
            // Check the mgmt version
            final HostInfo hostInfo = .;
            final int major = hostInfo.getManagementMajorVersion();
            final int minor = hostInfo.getManagementMinorVersion();
            final int micro = hostInfo.getManagementMicroVersion();
            boolean as711 = (major == 1 && minor == 1);
            if(as711) {
                        majorminor, 1, 2);
                .failed(failure);
                throw failure;
            }
            // Initialize the transformers
            final TransformationTarget target = TransformationTargetImpl.create(, ModelVersion.create(majorminormicro),
            final Transformers transformers = Transformers.Factory.create(target);
            try {
                SlaveChannelAttachments.attachSlaveInfo(.getChannel(), .transformers);
            } catch (IOException e) {
                throw new OperationFailedException(e.getLocalizedMessage());
            }
            // Build the extensions list
            final ModelNode extensions = new ModelNode();
            final Resource transformed = transformers.transformRootResource(contextroot);
            final Collection<Resource.ResourceEntryresources = transformed.getChildren();
            for(final Resource.ResourceEntry entry : resources) {
                extensions.add(entry.getName());
            }
            if(! extensions.isDefined()) {
                throw new OperationFailedException(extensions);
            }
            // Remotely resolve the subsystem versions and create the transformation
            .processSubsystems(transformersextensions);
            // Now run the read-domain model operation
            final ReadMasterDomainModelHandler handler = new ReadMasterDomainModelHandler(hostInfo.getHostName(), transformers);
            context.addStep(handler..);
            // Complete
            context.stepCompleted();
        }
    }
        private final TransformerRegistry transformerRegistry;
        private final boolean registerOnCompletion;
        private volatile String hostName;
        private volatile HostInfo hostInfo;
        private volatile IOTask<?> task;
        private volatile boolean failed;
        private volatile Transformers transformers;
        private final AtomicBoolean completed = new AtomicBoolean();
        private RegistrationContext(TransformerRegistry transformerRegistry) {
            this(transformerRegistrynullfalse);
        }
        private RegistrationContext(TransformerRegistry transformerRegistryDomainControllerRuntimeIgnoreTransformationRegistry runtimeIgnoreTransformationRegistry) {
            this(transformerRegistryruntimeIgnoreTransformationRegistrytrue);
        }
        private RegistrationContext(TransformerRegistry transformerRegistry,
                                    DomainControllerRuntimeIgnoreTransformationRegistry runtimeIgnoreTransformationRegistry,
                                    boolean registerOnCompletion) {
            this. = transformerRegistry;
            this. = runtimeIgnoreTransformationRegistry;
            this. = registerOnCompletion;
        }
        private synchronized void initialize(final String hostNamefinal ModelNode hostInfofinal ManagementRequestContext<RegistrationContextresponseChannel) {
            this. = hostName;
            this. = HostInfo.fromModelNode(hostInfo);
            this. = responseChannel;
            this. = DomainControllerRuntimeIgnoreTransformationEntry.create(this..getExtensionRegistry());
            if ( != null) {
                .initializeHost(hostName);
            }
        }
        @Override
        public void completed(Void result) {
            //
        }
        @Override
        public void failed(Exception e) {
            failed(..e.getClass().getName() + ":" + e.getMessage());
        }
        @Override
        public void cancelled() {
            //
        }
        @Override
        public void operationPrepared(final ModelController.OperationTransaction transactionfinal ModelNode result) {
            if() {
                if ( != null) {
                    .unregisterHost();
                }
                transaction.rollback();
            } else {
                try {
                    if () {
                        registerHost(transactionresult);
                    } else {
                        // Host just wanted the model; didn't register
                        sendResultToHost(transactionresult);
                    }
                } catch (SlaveRegistrationException e) {
                    failed(e.getErrorCode(), e.getErrorMessage());
                } catch (Exception e) {
                    failed(..e.getClass().getName() + ":" + e.getMessage());
                }
                if() {
                    transaction.rollback();
                }
            }
        }

        
Process the registration of the slave whose informatin was provided to initialize().
        private void processRegistration() {
            // Check for duplicate registrations
            if (.isHostRegistered()) {
                // asynchronously ping the existing host to validate it's still connected
                // If not, the ping will remove it and a subsequent attempt by the new host will succeed
                // TODO look into doing the ping synchronously
                .pingRemoteHost();
                // Quick hack -- wait a bit to let async ping detect a re-registration. This can easily be improved
                // via the TODO above
                boolean inter = false// TODO this is not used
                try {
                    Thread.sleep(500);
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt(); // TODO why not set inter = true and do this in finally?
                } finally {
                    // Now see if the existing registration has been removed
                    if (.isHostRegistered()) {
                    }
                }
            }
            if (!) {
                try {
                    // The domain model is going to be sent as part of the prepared notification
                    final OperationStepHandler handler = new HostRegistrationStepHandler(this);
                    ModelNode result = .execute(.this.handler);
                    if (.equals(result.get().asString())) {
                        failed(..result.get().asString());
                        return;
                    }
                } catch (Exception e) {
                    failed(e);
                    return;
                }
                // Send a registered notification back
                sendCompletedMessage();
                // Make sure that the host controller gets unregistered when the channel is closed
                .getChannel().addCloseHandler(new CloseHandler<Channel>() {
                    @Override
                    public void handleClose(Channel closedIOException exception) {
                        if (.isHostRegistered()) {
                            .lostConnectionToRemoteHost();
                        }
                        .unregisterRemoteHost(getRemoteConnectionId());
                    }
                });
            }
        }


        
Create the transformers. This will remotely resolve the subsystem versions.

Parameters:
extensions the extensions
Throws:
org.jboss.as.controller.OperationFailedException
        private void processSubsystems(final Transformers transformersfinal ModelNode extensionsthrows OperationFailedException {
            this. = transformers;
            final ModelNode subsystems = executeBlocking(new IOTask<ModelNode>() {
                @Override
                void sendMessage(FlushableDataOutput outputthrows IOException {
                    sendResponse(output.extensions);
                }
            });
            if() {
                throw new OperationFailedException(new ModelNode("failed to setup transformers"));
            }
            final TransformationTarget target = transformers.getTarget();
            for(final Property subsystem : subsystems.asPropertyList()) {
                final String subsystemName = subsystem.getName();
                final ModelNode version = subsystem.getValue();
                target.addSubsystemVersion(subsystemName, ModelVersion.fromString(version.asString()));
            }
        }
        protected void setSubsystems(final ModelNode resolvedfinal ManagementRequestContext<RegistrationContextresponseChannel) {
            this. = responseChannel;
            completeTask(resolved);
        }

        
Once the "read-domain-mode" operation is in operationPrepared, send the model back to registering HC. When the model was applied successfully on the client, we process registering the proxy in the domain, otherwise we rollback.

Parameters:
transaction the model controller tx
result the prepared result (domain model)
Throws:
org.jboss.as.domain.controller.SlaveRegistrationException
        void registerHost(final ModelController.OperationTransaction transactionfinal ModelNode resultthrows SlaveRegistrationException {
            //
            if (sendResultToHost(transactionresult)) return;
            synchronized (this) {
                Long pingPongId = .getRemoteConnectionId();
                // Register the slave
                // Complete registration
                if(! ) {
                    transaction.commit();
                } else {
                    transaction.rollback();
                    return;
                }
            }
        }
        private boolean sendResultToHost(ModelController.OperationTransaction transactionfinal ModelNode result) {
            final Boolean registered = executeBlocking(new IOTask<Boolean>() {
                @Override
                void sendMessage(final FlushableDataOutput outputthrows IOException {
                    sendResponse(output.result);
                }
            });
            if(! registered) {
                transaction.rollback();
                return true;
            }
            return false;
        }
        void completeRegistration(final ManagementRequestContext<RegistrationContextresponseChannelboolean commit) {
            this. = responseChannel;
             |= ! commit;
            completeTask(! );
        }
        void failed(SlaveRegistrationException.ErrorCode errorCodeString message) {
            failed(errorCode.getCode(), message);
        }
        void failed(byte errorCodeString message) {
            if(.compareAndSet(falsetrue)) {
                 = true;
                final IOTask<?> task = this.;
                if(task != null) {
                    task.setFailed();
                }
                try {
                    sendFailedResponse(errorCodemessage);
                } catch (IOException e) {
                    ..debugf(e"failed to process message");
                }
                .getResultHandler().done(null);
            }
        }
        void sendCompletedMessage() {
            if(.compareAndSet(falsetrue)) {
                try {
                    sendResponse(.null);
                } catch (IOException e) {
                    ..debugf(e"failed to process message");
                }
                .getResultHandler().done(null);
            }
        }
        Long getRemoteConnectionId() {
            return .getRemoteConnectionId();
        }
        protected boolean completeTask(Object result) {
            synchronized (this) {
                if() {
                    return false;
                }
                if( != null) {
                    return .completeStep(result);
                }
            }
            return false;
        }

        
Execute a task and wait for the response.

Parameters:
task the task to execute
<T> the response type
Returns:
the result
        protected <T> T executeBlocking(final IOTask<T> task) {
            synchronized (this) {
                this. = task;
                try {
                    final ManagementResponseHeader header = ManagementResponseHeader.create(.getRequestHeader());
                    final FlushableDataOutput output = .writeMessage(header);
                    try {
                        task.sendMessage(output);
                    } catch (IOException e) {
                        failed(..e.getMessage());
                        throw new IllegalStateException(e);
                    } finally {
                        StreamUtils.safeClose(output);
                    }
                } catch (IOException e) {
                    failed(..e.getMessage());
                    throw new IllegalStateException(e);
                }
            }
            try {
                return task.get();
            } catch (InterruptedException e) {
                failed(..e.getMessage());
                throw new IllegalStateException(e);
            } catch (ExecutionException e) {
                failed(..e.getMessage());
                throw new IllegalStateException(e);
            }
        }
    }
    abstract static class IOTask<T> extends AsyncFutureTask<T> {
        IOTask() {
            super(null);
        }
        abstract void sendMessage(final FlushableDataOutput outputthrows IOException;
        @SuppressWarnings("unchecked")
        boolean completeStep(Object result) {
            return setResult((T) result);
        }
        boolean setFailed() {
            return setFailed(null);
        }
    }

    
Send a operation response.

Parameters:
context the request context
responseType the response type
response the operation response
Throws:
java.io.IOException for any error
    static void sendResponse(final ManagementRequestContext<RegistrationContextcontextfinal byte responseTypefinal ModelNode responsethrows IOException {
        final ManagementResponseHeader header = ManagementResponseHeader.create(context.getRequestHeader());
        final FlushableDataOutput output = context.writeMessage(header);
        try {
            sendResponse(outputresponseTyperesponse);
        } finally {
            StreamUtils.safeClose(output);
        }
    }
    static void sendResponse(final FlushableDataOutput outputfinal byte responseTypefinal ModelNode responsethrows IOException {
        // response type
        output.writeByte(responseType);
        if(response != null) {
            // operation result
            response.writeExternal(output);
        }
        // response end
        output.close();
    }

    
Send a failed operation response.

Parameters:
context the request context
errorCode the error code
message the operation message
Throws:
java.io.IOException for any error
    static void sendFailedResponse(final ManagementRequestContext<RegistrationContextcontextfinal byte errorCodefinal String messagethrows IOException {
        final ManagementResponseHeader header = ManagementResponseHeader.create(context.getRequestHeader());
        final FlushableDataOutput output = context.writeMessage(header);
        try {
            // This is an error
            output.writeByte(.);
            // send error code
            output.writeByte(errorCode);
            // error message
            output.writeUTF(message);
            // response end
            output.writeByte(.);
            output.close();
        } finally {
            StreamUtils.safeClose(output);
        }
    }
New to GrepCode? Check out our FAQ X