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 java.security.AccessController.doPrivileged;
 import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.DOMAIN_MODEL;
 import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.EXTENSION;
 import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.FAILURE_DESCRIPTION;
 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.OPERATION_HEADERS;
 import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.OP_ADDR;
 import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.OUTCOME;
 import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.RESULT;
 import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.SERVER;
 import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.SUCCESS;
 import static org.jboss.as.host.controller.HostControllerLogger.ROOT_LOGGER;
 import static org.jboss.as.host.controller.HostControllerMessages.MESSAGES;
 
 import java.io.File;
 import java.net.URI;
 import java.util.List;
 
 
Establishes the connection from a slave org.jboss.as.domain.controller.DomainController to the master org.jboss.as.domain.controller.DomainController

Author(s):
Kabir Khan
    public static final String DOMAIN_CONNECTION_ID = "domain-connection-id";
    private static final int CONNECTION_TIMEOUT_DEFAULT = 30000;
    private static final String CONNECTION_TIMEOUT_PROPERTY = "jboss.host.domain.connection.timeout";
    private static final ModelNode APPLY_EXTENSIONS = new ModelNode();
    private static final ModelNode APPLY_DOMAIN_MODEL = new ModelNode();
    static {
        .get("execute-for-coordinator").set(true);
        .protect();
        //FIXME this makes the op work after boot (i.e. slave connects to restarted master), but does not make the slave resync the servers
        .get("execute-for-coordinator").set(true);
        .protect();
    }
    private final ExtensionRegistry extensionRegistry;
    private final ModelController controller;
    private final ProductConfig productConfig;
    private final LocalHostControllerInfo localHostInfo;
    private final DomainController domainController;
    private final RunningMode runningMode;

    
Used to invoke ModelController ops on the master
    private volatile ModelControllerClient masterProxy;
    private final FutureClient futureClient = new FutureClient();
    private final InjectedValue<EndpointendpointInjector = new InjectedValue<Endpoint>();
    private ExecutorService executor;
    private volatile RemoteDomainConnection connection;
    private RemoteDomainConnectionService(final ModelController controllerfinal ExtensionRegistry extensionRegistry,
                                          final LocalHostControllerInfo localHostControllerInfofinal ProductConfig productConfig,
                                          final RemoteFileRepository remoteFileRepository,
                                          final IgnoredDomainResourceRegistry ignoredDomainResourceRegistry,
                                          final HostControllerRegistrationHandler.OperationExecutor operationExecutor,
                                          final DomainController domainController,
                                          final HostControllerEnvironment hostControllerEnvironment,
                                          final RunningMode runningMode){
        this. = controller;
        this. = extensionRegistry;
        this. = productConfig;
        this. = localHostControllerInfo;
        this. = remoteFileRepository;
        this. = ignoredDomainResourceRegistry;
        this. = operationExecutor;
        this. = domainController;
        this. = hostControllerEnvironment;
        this. = runningMode;
    }
    public static Future<MasterDomainControllerClientinstall(final ServiceTarget serviceTargetfinal ModelController controllerfinal ExtensionRegistry extensionRegistry,
                                                               final LocalHostControllerInfo localHostControllerInfofinal ProductConfig productConfig,
                                                               final String securityRealmfinal RemoteFileRepository remoteFileRepository,
                                                               final IgnoredDomainResourceRegistry ignoredDomainResourceRegistry,
                                                               final HostControllerRegistrationHandler.OperationExecutor operationExecutor,
                                                               final DomainController domainController,
                                                               final HostControllerEnvironment hostControllerEnvironment,
                                                               final RunningMode currentRunningMode) {
        RemoteDomainConnectionService service = new RemoteDomainConnectionService(controllerextensionRegistrylocalHostControllerInfo,
                productConfigremoteFileRepositoryignoredDomainResourceRegistryoperationExecutordomainController,
                hostControllerEnvironmentcurrentRunningMode);
                .addDependency(.Endpoint.classservice.endpointInjector)
                .addDependency(.ServerInventory.classservice.serverInventoryInjector)
                .setInitialMode(..);
        if (securityRealm != null) {
            SecurityRealm.ServiceUtil.addDependency(builderservice.securityRealmInjectorsecurityRealmfalse);
        }
        builder.install();
        return service.futureClient;
    }

    
    public synchronized void register() throws IOException {
        boolean connected = false;
        // Loop through discovery options
        for (Iterator<DiscoveryOptioni = discoveryOptions.iterator(); i.hasNext(); ) {
           DiscoveryOption discoveryOption = i.next();
           final long timeout = ;
           final long endTime = System.currentTimeMillis() + timeout;
           int retries = 0;
           String host = null;
           int port = -1;
           try {
               // Determine the remote DC host and port to use
               discoveryOption.discover();
               host = discoveryOption.getRemoteDomainControllerHost();
               port = discoveryOption.getRemoteDomainControllerPort();
               .setUri(new URI("remote://" + NetworkUtils.formatPossibleIpv6Address(host) + ":" + port));
               while (!connected) {
                   try {
                       // Try to connect to the domain controller
                       .connect();
                       connected = true;
                   } catch (IOException e) {
                       Throwable cause = e;
                       ..debugf(e"failed to connect to %s:%d"hostport);
                       while ((cause = cause.getCause()) != null) {
                           if (cause instanceof SaslException) {
                               throw .authenticationFailureUnableToConnect(cause);
                           } else if (cause instanceof SSLHandshakeException) {
                               throw .sslFailureUnableToConnect(cause);
                           } else if (cause instanceof SlaveRegistrationException) {
                               throw new IOException(cause);
                           }
                       }
                       if (System.currentTimeMillis() > endTime) {
                           throw .connectionToMasterTimeout(eretriestimeout);
                       }
                       try {
                           ..cannotConnect(hostporte);
                           ..wait(retries);
                           retries++;
                       } catch (InterruptedException ie) {
                           throw .connectionToMasterInterrupted();
                       }
                   }
               }
               if(connected) {
                   // Setup the transaction protocol handler
                   // Use the existing channel strategy
                    = ExistingChannelModelControllerClient.createAndAdd();
                    = new TransactionalDomainControllerClient();
                   break;
               }
           } catch (Exception e) {
               if (i.hasNext()) {
                   ..tryingAnotherDiscoveryOption(e);
               } else {
                   // All discovery options have been exhausted
                   ..noDiscoveryOptionsLeft(e);
                   throw .discoveryOptionsFailureUnableToConnect(e);
               }
           }
        }
    }

    
    public synchronized void unregister() {
        StreamUtils.safeClose();
    }
    @Override
    public void fetchDomainWideConfiguration() {
        try {
            //TODO implement fetchDomainWideConfiguration
            throw new UnsupportedOperationException();
        } finally {
            StreamUtils.safeClose();
        }
    }

    
    public synchronized HostFileRepository getRemoteFileRepository() {
        return ;
    }
    @Override
    public ModelNode execute(ModelNode operationthrows IOException {
        return execute(operation.);
    }
    @Override
    public ModelNode execute(Operation operationthrows IOException {
        return .execute(operation.);
    }
    @Override
    public ModelNode execute(ModelNode operationOperationMessageHandler messageHandlerthrows IOException {
        return .execute(operationmessageHandler);
    }
    @Override
    public ModelNode execute(Operation operationOperationMessageHandler messageHandlerthrows IOException {
        return .execute(operationmessageHandler);
    }
    @Override
    public AsyncFuture<ModelNodeexecuteAsync(ModelNode operationOperationMessageHandler messageHandler) {
        return .executeAsync(operationmessageHandler);
    }
    @Override
    public AsyncFuture<ModelNodeexecuteAsync(Operation operationOperationMessageHandler messageHandler) {
        return .executeAsync(operationmessageHandler);
    }
    @Override
    public void pullDownDataForUpdatedServerConfigAndApplyToModel(OperationContext contextString serverNameString serverGroupNameString socketBindingGroupNamethrows OperationFailedException {
        ModelNode op = new ModelNode();
        op.get().setEmptyList();
        op.get().set(IgnoredNonAffectedServerGroupsUtil.createServerConfigInfo(serverNameserverGroupNamesocketBindingGroupName).toModelNode());
        if (domainControllerLock != null) {
            op.get(.).set(domainControllerLock);
        }
        ModelNode result = .executeTransactional(contextop);
        if (result.get().isDefined()) {
            throw new OperationFailedException(result.get().asString());
        }
        ModelNode applyMissingResourcesOp = ApplyMissingDomainModelResourcesHandler.createPulledMissingDataOperation(result.get());
        context.addStep(applyMissingResourcesOpapplyMissingDomainModelResourcesHandler..true);
    }
    @Override
    public void close() throws IOException {
        throw .closeShouldBeManagedByService();
    }

    
    @Override
    public synchronized void start(StartContext contextthrows StartException {
        final RemoteDomainConnection connection;
        final ManagementChannelHandler handler;
        try {
            ThreadFactory threadFactory = new JBossThreadFactory(new ThreadGroup("domain-connection-threads"), .null"%G - %t"nullnulldoPrivileged(GetAccessControlContextAction.getInstance()));
            this. = Executors.newCachedThreadPool(threadFactory);
            ThreadFactory scheduledThreadFactory = new JBossThreadFactory(new ThreadGroup("domain-connection-pinger-threads"), .null"%G - %t"nullnulldoPrivileged(GetAccessControlContextAction.getInstance()));
            this. = Executors.newSingleThreadScheduledExecutor(scheduledThreadFactory);
            // Include additional local host information when registering at the DC
            final ModelNode hostInfo = HostInfo.createLocalHostHostInfo(, ReadRootResourceHandler.grabDomainResource().getChildren().iterator().next());
            final OptionMap options = OptionMap.builder().set(., 15000)
                    .set(., 45000)
            // Gather the required information to connect to the remote DC
            final ProtocolChannelClient.Configuration configuration = new ProtocolChannelClient.Configuration();
            // The URI will be set accordingly when looping through discovery options when registering with
            // or reconnecting to the remote DC.
            configuration.setEndpoint(.getValue());
            configuration.setOptionMap(options);
            final SecurityRealm realm = .getOptionalValue();
            // Create the remote domain channel strategy
            connection = new RemoteDomainConnection(.getLocalHostName(), hostInfoconfigurationrealm,
                    .getRemoteDomainControllerUsername(),
                    new RemoteDomainConnection.HostRegistrationCallback() {
                @Override
                public ModelNode resolveSubsystemVersions(ModelNode extensions) {
                    return resolveSubsystems(extensions.asList());
                }
                        @Override
                public boolean applyDomainModel(final List<ModelNodebootOperations) {
                    // Apply the model..
                    return applyRemoteDomainModel(bootOperations);
                }
                @Override
                public void registrationComplete(ManagementChannelHandler handler) {
                    //
                }
            }, );
            // Setup the management channel handler
            handler = connection.getChannelHandler();
        } catch (Exception e) {
            throw new StartException(e);
        } finally {
            .setClient(this);
        }
        this. = connection;
        this. = handler;
    }

    
Resolve the subsystem versions.

Parameters:
extensions the extensions to install
Returns:
the subsystem versions
    private ModelNode resolveSubsystems(final List<ModelNodeextensions) {
        final List<ModelNodebootOperations = new ArrayList<ModelNode>();
        for (final ModelNode extension : extensions) {
            final ModelNode e = new ModelNode();
            e.get("domain-resource-address").add(extension.asString());
            bootOperations.add(e);
        }
        final ModelNode operation = .clone();
        operation.get().set(bootOperations);
        if (!.equals(result.get().asString())) {
        }
        final ModelNode subsystems = new ModelNode();
        for (final ModelNode extension : extensions) {
            .recordSubsystemVersions(extension.asString(), subsystems);
        }
        return subsystems;
    }

    
Apply the remote domain model to the local host controller.

Parameters:
bootOperations the result of the remote read-domain-model op
Returns:
true if the model was applied successfully, false otherwise
    private boolean applyRemoteDomainModel(final List<ModelNodebootOperations) {
        final ModelNode result;
        try {
            // Create the apply-domain-model operation
            final ModelNode operation = .clone();
            operation.get().set(bootOperations);
            // Execute the operation
        } catch (Exception e) {
            return false;
        }
        // If it did not success, don't register it at the DC
        String outcome = result.get().asString();
        boolean success = .equals(outcome);
        if (!success) {
            ModelNode failureDesc = result.hasDefined() ? result.get() : new ModelNode();
            ..failedToApplyDomainConfig(outcomefailureDesc);
        }
        return success;
    }

    
    @Override
    public synchronized void stop(final StopContext context) {
        Thread executorShutdown = new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    StreamUtils.safeClose();
                    .shutdownNow();
                } finally {
                    try {
                        .shutdown();
                    } finally {
                        context.complete();
                    }
                }
            }
        }, RemoteDomainConnectionService.class.getSimpleName() + " ExecutorService Shutdown Thread");
        executorShutdown.start();
        context.asynchronous();
    }

    
    @Override
        return this;
    }
    private class GetFileRequest extends AbstractManagementRequest<FileVoid> {
        private final byte rootId;
        private final String filePath;
        private final HostFileRepository localFileRepository;
        private GetFileRequest(final byte rootIdfinal String filePathfinal HostFileRepository localFileRepository) {
            this. = rootId;
            this. = filePath;
            this. = localFileRepository;
        }
        @Override
        public byte getOperationType() {
            return .;
        }
        @Override
        protected void sendRequest(ActiveOperation.ResultHandler<FileresultHandlerManagementRequestContext<VoidcontextFlushableDataOutput outputthrows IOException {
            output.write(.);
            output.writeUTF(.getLocalHostName());
        }
        @Override
        public void handleRequest(DataInput inputActiveOperation.ResultHandler<FileresultHandlerManagementRequestContext<Voidcontextthrows IOException {
            final File localPath;
            switch () {
                case .: {
                    localPath = .getFile();
                    break;
                }
                case .: {
                    localPath = .getConfigurationFile();
                    break;
                }
                case .: {
                    byte[] hash = HashUtil.hexStringToByteArray();
                    localPath = .getDeploymentRoot(hash);
                    break;
                }
                default: {
                    localPath = null;
                }
            }
            try {
                ..handleResponse(inputlocalPathresultHandlercontext);
            } catch (CannotCreateLocalDirectoryException e) {
                throw .cannotCreateLocalDirectory(e.getDir());
            } catch (DidNotReadEntireFileException e) {
                throw .didNotReadEntireFile(e.getMissing());
            }
        }
    }
    static class RemoteFileRepository implements HostFileRepository {
        private final HostFileRepository localFileRepository;
        RemoteFileRepository(final HostFileRepository localFileRepository) {
            this. = localFileRepository;
        }
        @Override
        public final File getFile(String relativePath) {
            return getFile(relativePath.);
        }
        @Override
        public final File getConfigurationFile(String relativePath) {
            return getFile(relativePath.);
        }
        @Override
        public final File[] getDeploymentFiles(byte[] deploymentHash) {
            final File root = getDeploymentRoot(deploymentHash);
            return root.listFiles();
        }
        @Override
        public File getDeploymentRoot(byte[] deploymentHash) {
            String hex = deploymentHash == null ? "" : HashUtil.bytesToHexString(deploymentHash);
            final File file = .getDeploymentRoot(deploymentHash);
            if(! file.exists()) {
                return getFile(hex.);
            }
            return file;
        }
        private File getFile(final String relativePathfinal byte repoId) {
            return .getFile(relativePathrepoId);
        }
        void setRemoteFileRepositoryExecutor(RemoteFileRepositoryExecutor remoteFileRepositoryExecutor) {
            this. = remoteFileRepositoryExecutor;
        }
        @Override
        public void deleteDeployment(byte[] deploymentHash) {
            .deleteDeployment(deploymentHash);
        }
    }
    interface RemoteFileRepositoryExecutor {
        File getFile(final String relativePathfinal byte repoIdHostFileRepository localFileRepository);
    }
        public File getFile(final String relativePathfinal byte repoIdHostFileRepository localFileRepository) {
            if(.isConnected()) {
                try {
                    return .executeRequest(new GetFileRequest(repoIdrelativePathlocalFileRepository), null).getResult().get();
                } catch (Exception e) {
                    throw .failedToGetFileFromRemoteRepository(e);
                }
            } else {
                return localFileRepository.getFile(relativePath);
            }
        }
    };
        protected FutureClient() {
            super(null);
        }
        private void setClient(MasterDomainControllerClient client) {
            super.setResult(client);
        }
    }
    private static int getSystemProperty(final String namefinal int defaultValue) {
        final String value = WildFlySecurityManager.getPropertyPrivileged(namenull);
        try {
            return value == null ? defaultValue : Integer.parseInt(value);
        } catch (NumberFormatException ignored) {
            return defaultValue;
        }
    }
    private static class ReadRootResourceHandler implements OperationStepHandler {
        private Resource resource;
            ReadRootResourceHandler handler = new ReadRootResourceHandler();
            executor.execute(new ModelNode(), ...nullhandler);
            return handler.resource;
        }
        @Override
        public void execute(OperationContext contextModelNode operationthrows OperationFailedException {
             = context.readResourceFromRoot(.);
            context.stepCompleted();
        }
    }

    
The tx handling code is copied from ProxyStepHandler
    private static class TransactionalDomainControllerClient {
        private final RemoteProxyController remoteProxy;
             = RemoteProxyController.create(handler..false);
        }
        private ModelNode executeTransactional(OperationContext contextModelNode operation) {
            OperationMessageHandler messageHandler = new DelegatingMessageHandler(context);
            final AtomicReference<ModelNodepreparedResultRef = new AtomicReference<ModelNode>();
            final AtomicReference<ModelNodefinalResultRef = new AtomicReference<ModelNode>();
            final ProxyController.ProxyOperationControl proxyControl = new ProxyController.ProxyOperationControl() {
                @Override
                public void operationPrepared(ModelController.OperationTransaction transactionModelNode result) {
                    txRef.set(transaction);
                    preparedResultRef.set(result);
                }
                @Override
                public void operationFailed(ModelNode response) {
                    finalResultRef.set(response);
                }
                @Override
                public void operationCompleted(ModelNode response) {
                    finalResultRef.set(response);
                }
            };
            .execute(operationmessageHandlerproxyControlnew DelegatingOperationAttachments(context));
            ModelNode finalResult = finalResultRef.get();
            if (finalResult != null) {
                // operation failed before it could commit
                return finalResult;
            }
            context.addStep(new OperationStepHandler() {
                @Override
                public void execute(OperationContext contextModelNode operationthrows OperationFailedException {
                    completeRemoteTransaction(contextoperationtxRefpreparedResultReffinalResultRef);
                }
            }, ..);
            return preparedResultRef.get();
        }
        private void completeRemoteTransaction(OperationContext contextModelNode operation,
                final AtomicReference<ModelController.OperationTransactiontxRef,
                final AtomicReference<ModelNodepreparedResultReffinal AtomicReference<ModelNodefinalResultRef) {
            boolean completeStepCalled = false;
            try {
                context.completeStep(new OperationContext.ResultHandler() {
                    @Override
                    public void handleResult(OperationContext.ResultAction resultActionOperationContext contextModelNode operation) {
                        boolean txCompleted = false;
                        try {
                            ModelController.OperationTransaction tx = txRef.get();
                            try {
                                if (resultAction == ..) {
                                    tx.commit();
                                } else {
                                    tx.rollback();
                                }
                            } finally {
                                txCompleted = true;
                            }
                        } finally {
                            // Ensure the remote side gets a transaction outcome if
                            // we can't commit/rollback above
                            if (!txCompleted && txRef.get() != null) {
                                txRef.get().rollback();
                            }
                        }
                    }
                });
                completeStepCalled = true;
            } finally {
                // Ensure the remote side gets a transaction outcome if we can't
                // call completeStep above
                if (!completeStepCalled && txRef.get() != null) {
                    txRef.get().rollback();
                }
            }
        }
    }
    private static class DelegatingMessageHandler implements OperationMessageHandler {
        private final OperationContext context;
        DelegatingMessageHandler(final OperationContext context) {
            this. = context;
        }
        @Override
        public void handleReport(MessageSeverity severityString message) {
            .report(severitymessage);
        }
    }
    private static class DelegatingOperationAttachments implements OperationAttachments {
        private final OperationContext context;
        private DelegatingOperationAttachments(final OperationContext context) {
            this. = context;
        }
        @Override
        public boolean isAutoCloseStreams() {
            return false;
        }
        @Override
        public List<InputStreamgetInputStreams() {
            int count = .getAttachmentStreamCount();
            List<InputStreamresult = new ArrayList<InputStream>(count);
            for (int i = 0; i < counti++) {
                result.add(.getAttachmentStream(i));
            }
            return result;
        }
        @Override
        public void close() throws IOException {
            //
        }
    }