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.domain.controller.operations.coordination;
 
 import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.CANCELLED;
 import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.COMPOSITE;
 import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.CONCURRENT_GROUPS;
 import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.DOMAIN_FAILURE_DESCRIPTION;
 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.HOST_FAILURE_DESCRIPTIONS;
 import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.IN_SERIES;
 import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.MAX_FAILED_SERVERS;
 import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.MAX_FAILURE_PERCENTAGE;
 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.OUTCOME;
 import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.RESULT;
 import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.ROLLBACK_ACROSS_GROUPS;
 import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.ROLLING_TO_SERVERS;
 import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.SERVERS;
 import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.SERVER_GROUP;
 import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.SERVER_OPERATIONS;
 import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.STEPS;
 import static org.jboss.as.domain.controller.DomainControllerLogger.HOST_CONTROLLER_LOGGER;
 import static org.jboss.as.domain.controller.DomainControllerMessages.MESSAGES;
 
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
 
Formulates a rollout plan, invokes the proxies to execute it on the servers.

Author(s):
Brian Stansberry (c) 2011 Red Hat Inc.
 
 public class DomainRolloutStepHandler implements OperationStepHandler {
 
     private final Map<StringProxyControllerhostProxies;
     private final Map<StringProxyControllerserverProxies;
     private final ExecutorService executorService;
     private final ModelNode providedRolloutPlan;
     private final boolean trace = .isTraceEnabled();
 
     public DomainRolloutStepHandler(final Map<StringProxyControllerhostProxies,
                                     final Map<StringProxyControllerserverProxies,
                                     final DomainOperationContext domainOperationContext,
                                     final ModelNode rolloutPlan,
                                     final ExecutorService executorService) {
         this. = hostProxies;
         this. = serverProxies;
         this. = domainOperationContext;
         this. = rolloutPlan;
         this. = executorService;
     }
 
    @Override
    public void execute(final OperationContext contextfinal ModelNode operationthrows OperationFailedException {
        if (context.hasFailureDescription()) {
            // abort
            context.setRollbackOnly();
            context.stepCompleted();
            return;
        }
        // Temporary hack to prevent CompositeOperationHandler throwing away domain failure data
        // Confirm no host failures
        boolean pushToServers = !.hasHostLevelFailures();
        if (pushToServers) {
            ModelNode ourResult = .getCoordinatorResult();
            if (ourResult.has()) {
                if () {
                    .tracef("coordinator failed: %s"ourResult);
                }
                pushToServers = false;
                .setCompleteRollback(true);
            } else {
                if () {
                    .tracef("coordinator succeeded: %s"ourResult);
                }
                for (ModelNode hostResult : .getHostControllerResults().values()) {
                    if (hostResult.has()) {
                        if () {
                            .tracef("host failed: %s"hostResult);
                        }
                        pushToServers = false;
                        .setCompleteRollback(true);
                        break;
                    }
                }
            }
        }
        if (pushToServers) {
            // We no longer roll back by default
            .setCompleteRollback(false);
            final List<ServerTaskExecutor.ServerPreparedResponsepreparedResults = new ArrayList<ServerTaskExecutor.ServerPreparedResponse>();
            boolean completeStepCalled = false;
            try {
                pushToServers(contextsubmittedTaskspreparedResults);
                context.completeStep(new OperationContext.ResultHandler() {
                    @Override
                    public void handleResult(OperationContext.ResultAction resultActionOperationContext contextModelNode operation) {
                        finalizeOp(submittedTaskspreparedResults);
                    }
                });
                completeStepCalled = true;
            } finally {
                if (!completeStepCalled) {
                    finalizeOp(submittedTaskspreparedResults);
                }
            }
        } else {
            // There were failures on hosts, so gather them up and report them
            reportHostFailures(contextoperation);
        }
    }
    private void finalizeOp(final Map<ServerIdentityServerTaskExecutor.ExecutedServerRequestsubmittedTasks,
                            final List<ServerTaskExecutor.ServerPreparedResponsepreparedResults) {
        // Inform the remote hosts whether to commit or roll back their updates
        // Do them all before reading results so the commits/rollbacks can be executed in parallel
        boolean completeRollback = .isCompleteRollback();
        final String localHostName = .getLocalHostInfo().getLocalHostName();
        for(final ServerTaskExecutor.ServerPreparedResponse preparedResult : preparedResults) {
            boolean rollback = completeRollback || .isServerGroupRollback(preparedResult.getServerGroupName());
            // Require a server reload, in case the operation failed, but the overall state was commit
            if(! preparedResult.finalizeTransaction(! rollback)) {
                final ServerIdentity identity = preparedResult.getServerIdentity();
                try {
                    // Replace the original proxyTask with the requireReloadTask
                    final ModelNode result = preparedResult.getPreparedOperation().getPreparedResult();
                    ProxyController proxy = .get(identity.getHostName());
                    if (proxy == null) {
                        if (localHostName.equals(identity.getHostName())) {
                            // Use our server proxies
                            proxy = .get(identity.getServerName());
                            if (proxy == null) {
                                if () {
                                    .tracef("No proxy for %s"identity);
                                }
                                continue;
                            }
                        }
                    }
                    final Future<ModelNodefuture = .submit(new ServerRequireRestartTask(identityproxyresult));
                    // replace the existing future
                    submittedTasks.put(identitynew ServerTaskExecutor.ExecutedServerRequest(identityfuture));
                } catch (Exception ignore) {
                    // getUncommittedResult() won't fail here
                }
            }
        }
        // Now read the final values. This ensures the operations are committed on the remote servers
        // before we expose the servers to further requests
        boolean interrupted = false;
        try {
            for (Map.Entry<ServerIdentityServerTaskExecutor.ExecutedServerRequestentry : submittedTasks.entrySet()) {
                final ServerTaskExecutor.ExecutedServerRequest request = entry.getValue();
                final Future<ModelNodefuture = request.getFinalResult();
                try {
                    final ModelNode finalResult = future.isCancelled() ? getCancelledResult() : future.get();
                    final ModelNode transformedResult = request.transformResult(finalResult);
                    .addServerResult(entry.getKey(), transformedResult);
                } catch (InterruptedException e) {
                    interrupted = true;
                    .interruptedAwaitingFinalResponse(entry.getKey().getServerName(), entry.getKey().getHostName());
                } catch (ExecutionException e) {
                    .caughtExceptionAwaitingFinalResponse(e.getCause(), entry.getKey().getServerName(), entry.getKey().getHostName());
                }
            }
        } finally {
            if (interrupted) {
                Thread.currentThread().interrupt();
            }
        }
    }
    private ModelNode getCancelledResult() {
        ModelNode cancelled = new ModelNode();
        cancelled.get().set();
        return cancelled;
    }
    private void pushToServers(final OperationContext contextfinal Map<ServerIdentity,ServerTaskExecutor.ExecutedServerRequestsubmittedTasks,
                               final List<ServerTaskExecutor.ServerPreparedResponsepreparedResultsthrows OperationFailedException {
        final String localHostName = .getLocalHostInfo().getLocalHostName();
            hostResults.put(localHostName.getCoordinatorResult());
        }
        Map<StringMap<ServerIdentityModelNode>> opsByGroup = getOpsByGroup(hostResults);
        if (opsByGroup.size() > 0) {
            final ModelNode rolloutPlan = getRolloutPlan(this.opsByGroup);
            if () {
                .tracef("Rollout plan is %s"rolloutPlan);
            }
            final ServerTaskExecutor taskExecutor = new ServerTaskExecutor(contextsubmittedTaskspreparedResults) {
                @Override
                protected boolean execute(TransactionalProtocolClient.TransactionalOperationListener<ServerTaskExecutor.ServerOperationlistenerServerIdentity serverModelNode originalthrows OperationFailedException {
                    final String hostName = server.getHostName();
                    ProxyController proxy = .get(hostName);
                    if (proxy == null) {
                        if (localHostName.equals(hostName)) {
                            // Use our server proxies
                            proxy = .get(server.getServerName());
                        }
                        if (proxy == null) {
                            if () {
                                .tracef("No proxy for %s"server);
                            }
                            return false;
                        }
                    }
                    // Transform the server-results
                    final TransformingProxyController remoteProxyController = (TransformingProxyControllerproxy;
                    final OperationTransformer.TransformedOperation transformed = .transformServerOperation(hostNameremoteProxyControllercontextoriginal);
                    final ModelNode transformedOperation = transformed.getTransformedOperation();
                    final OperationResultTransformer resultTransformer = transformed.getResultTransformer();
                    final TransactionalProtocolClient client = remoteProxyController.getProtocolClient();
                    return executeOperation(listenerclientservertransformedOperationresultTransformer);
                }
            };
            RolloutPlanController rolloutPlanController = new RolloutPlanController(opsByGrouprolloutPlantaskExecutor);
            RolloutPlanController.Result planResult = rolloutPlanController.execute();
            if () {
                .tracef("Rollout plan result is %s"planResult);
            }
            if (planResult == .. ||
                    (planResult == .. && .isCompleteRollback())) {
                .setCompleteRollback(true);
                // AS7-801 -- we need to record a failure description here so the local host change gets aborted
                // Waiting to do it in the DomainFinalResultHandler on the way out is too late
                // Create the result node first so the server results will end up before the failure stuff
                context.getResult();
                context.getFailureDescription().set(.operationFailedOrRolledBack());
                .setFailureReported(true);
            }
        }
    }
    private Map<StringMap<ServerIdentityModelNode>> getOpsByGroup(Map<StringModelNodehostResults) {
        Map<StringMap<ServerIdentityModelNode>> result = new HashMap<StringMap<ServerIdentityModelNode>>();
        for (Map.Entry<StringModelNodeentry : hostResults.entrySet()) {
            if () {
                .tracef("1st phase result from host %s is %s"entry.getKey(), entry.getValue());
            }
            ModelNode hostResult = entry.getValue().get();
            if (hostResult.hasDefined()) {
                String host = entry.getKey();
                for (ModelNode item : hostResult.get().asList()) {
                    ModelNode op = translateDomainMappedOperation(item.require());
                    for (Property prop : item.require().asPropertyList()) {
                        String group = prop.getValue().asString();
                        Map<ServerIdentityModelNodegroupMap = result.get(group);
                        if (groupMap == null) {
                            groupMap = new HashMap<ServerIdentityModelNode>();
                            result.put(groupgroupMap);
                        }
                        groupMap.put(new ServerIdentity(hostgroupprop.getName()), op);
                    }
                }
            }
        }
        return result;
    }
    private ModelNode translateDomainMappedOperation(final ModelNode domainMappedOperation) {
        if (domainMappedOperation.hasDefined()) {
            // Simple op; return it
            return domainMappedOperation;
        }
        ModelNode composite = new ModelNode();
        composite.get().set();
        ModelNode steps = composite.get().setEmptyList();
        for (Property property : domainMappedOperation.asPropertyList()) {
            steps.add(translateDomainMappedOperation(property.getValue()));
        }
        return composite;
    }
    private ModelNode getRolloutPlan(ModelNode rolloutPlanMap<StringMap<ServerIdentityModelNode>> opsByGroupthrows OperationFailedException {
        if (rolloutPlan == null || !rolloutPlan.isDefined()) {
            rolloutPlan = getDefaultRolloutPlan(opsByGroup);
        }
        else {
            // Validate that plan covers all groups
            Set<Stringfound = new HashSet<String>();
            if (rolloutPlan.hasDefined()) {
                for (ModelNode series : rolloutPlan.get().asList()) {
                    if (series.hasDefined()) {
                        for(Property prop : series.get().asPropertyList()) {
                            validateServerGroupPlan(foundprop);
                        }
                    }
                    else if (series.hasDefined()) {
                        Property prop = series.get().asProperty();
                        validateServerGroupPlan(foundprop);
                    }
                    else {
                        throw new OperationFailedException(new ModelNode().set(.invalidRolloutPlan(series)));
                    }
                }
            }
            Set<Stringgroups = new HashSet<String>(opsByGroup.keySet());
            groups.removeAll(found);
            if (!groups.isEmpty()) {
                throw new OperationFailedException(new ModelNode().set(.invalidRolloutPlan(groups)));
            }
        }
        return rolloutPlan;
    }
    private void validateServerGroupPlan(Set<StringfoundProperty propthrows OperationFailedException {
        if (!found.add(prop.getName())) {
        }
        ModelNode plan = prop.getValue();
        if (plan.hasDefined()) {
            if (plan.has()) {
                plan.remove();
            }
            int max = plan.get().asInt();
            if (max < 0 || max > 100) {
                throw new OperationFailedException(new ModelNode().set(.invalidRolloutPlanRange(prop.getName(), max)));
            }
        }
        if (plan.hasDefined()) {
            int max = plan.get().asInt();
            if (max < 0) {
                throw new OperationFailedException(new ModelNode().set(.invalidRolloutPlanLess(prop.getName(), max)));
            }
        }
    }
    private ModelNode getDefaultRolloutPlan(Map<StringMap<ServerIdentityModelNode>> opsByGroup) {
        ModelNode result = new ModelNode();
        if (opsByGroup.size() > 0) {
            ModelNode groups = result.get().add().get();
            ModelNode groupPlan = new ModelNode();
            groupPlan.get().set(false);
            groupPlan.get().set(0);
            for (String group : opsByGroup.keySet()) {
                groups.add(groupgroupPlan);
            }
            result.get().set(true);
        }
        return result;
    }
    private void reportHostFailures(final OperationContext contextfinal ModelNode operation) {
        final boolean isDomain = isDomainOperation(operation);
        if (!collectDomainFailure(contextisDomain)) {
            collectHostFailures(contextisDomain);
        }
    }
    private boolean collectDomainFailure(OperationContext contextfinal boolean isDomain) {
        final ModelNode coordinator = .getCoordinatorResult();
        ModelNode domainFailure = null;
        if (isDomain &&  coordinator != null && coordinator.has()) {
            domainFailure = coordinator.hasDefined() ? coordinator.get() : new ModelNode().set(.unexplainedFailure());
        }
        if (domainFailure != null) {
            context.getFailureDescription().get().set(domainFailure);
            .setFailureReported(true);
            return true;
        }
        return false;
    }
    private boolean collectHostFailures(final OperationContext contextfinal boolean isDomain) {
        ModelNode hostFailureResults = null;
            ModelNode hostResult = entry.getValue();
            if (hostResult.has()) {
                if (hostFailureResults == null) {
                    hostFailureResults = new ModelNode();
                }
                final ModelNode desc = hostResult.hasDefined() ? hostResult.get() : new ModelNode().set(.unexplainedFailure());
                hostFailureResults.add(entry.getKey(), desc);
            }
        }
        final ModelNode coordinator = .getCoordinatorResult();
        if (!isDomain && coordinator != null && coordinator.has()) {
            if (hostFailureResults == null) {
                hostFailureResults = new ModelNode();
            }
            final ModelNode desc = coordinator.hasDefined() ? coordinator.get() : new ModelNode().set(.unexplainedFailure());
            hostFailureResults.add(.getLocalHostInfo().getLocalHostName(), desc);
        }
        if (hostFailureResults != null) {
            context.getFailureDescription().get().set(hostFailureResults);
            .setFailureReported(true);
            return true;
        }
        return false;
    }
    private boolean isDomainOperation(final ModelNode operation) {
        final PathAddress address = PathAddress.pathAddress(operation.require());
        return address.size() == 0 || !address.getElement(0).getKey().equals();
    }
New to GrepCode? Check out our FAQ X