Package com.webobjects.monitor.application.starter

Source Code of com.webobjects.monitor.application.starter.RollingShutdownBouncer

package com.webobjects.monitor.application.starter;

import com.webobjects.foundation.NSArray;
import com.webobjects.foundation.NSMutableArray;
import com.webobjects.monitor._private.MApplication;
import com.webobjects.monitor._private.MHost;
import com.webobjects.monitor._private.MInstance;

/**
* Bounces an application using a rolling shutdown.
*
* It does so by starting at least one inactive instance per active host
* (or 10 % of the total active instance count), waiting until they have started,
* then forcefully restarting each instance one at a time until they have all
* been restarted.
*
* You must have at least one inactive instance in order to perform this bounce.
*
* @author johnthuss
*/
public class RollingShutdownBouncer extends ApplicationStarter {

    public RollingShutdownBouncer(MApplication app) {
        super(app);
    }

    @Override
    protected void bounce() throws InterruptedException {

        NSArray<MInstance> instances = application().instanceArray().immutableClone();
        NSArray<MInstance> runningInstances = application().runningInstances_M();
        NSArray<MHost> activeHosts = (NSArray<MHost>) runningInstances.valueForKeyPath("host.@unique");

        NSMutableArray<MInstance> inactiveInstances = instances.mutableClone();
        inactiveInstances.removeObjectsInArray(runningInstances);

        if (inactiveInstances.isEmpty()) {
          addObjectsFromArrayIfAbsentToErrorMessageArray(
              new NSArray<String>("You must have at least one inactive instance to perform a rolling shutdown bounce."));
          return;
        }
       
        int numInstancesToStartPerHost = numInstancesToStartPerHost(runningInstances, activeHosts);
        NSArray<MInstance> startingInstances = instancesToStart(inactiveInstances, activeHosts, numInstancesToStartPerHost);
       
        boolean useScheduling = doAllRunningInstancesUseScheduling(runningInstances);
        log("Starting inactive instances");
        startInstances(startingInstances, activeHosts, useScheduling);
       
        waitForInactiveInstancesToStart(startingInstances, activeHosts);
       
       
        NSMutableArray<MInstance> restartingInstances = runningInstances.mutableClone();
        refuseNewSessions(restartingInstances, activeHosts);
       
        NSMutableArray<MInstance> stoppingInstances = new NSMutableArray<MInstance>();
        for (int i = numInstancesToStartPerHost; i > 0; i--) {
          if (restartingInstances.isEmpty()) {
            break;
          }
          stoppingInstances.addObject(restartingInstances.removeLastObject());
    }
       
        restartInstances(restartingInstances, activeHosts, useScheduling);
        stopInstances(stoppingInstances, activeHosts);
       
       
        handler().startReading();
        try {
            handler().getInstanceStatusForHosts(activeHosts);
            log("Finished");
        } finally {
            handler().endReading();
        }
    }

  protected int numInstancesToStartPerHost(NSArray<MInstance> runningInstances, NSArray<MHost> activeHosts) {
    int numToStartPerHost = 1;
        if (activeHosts.count() > 0) {
            numToStartPerHost = (int) (runningInstances.count() / activeHosts.count() * .1);
        }
        if (numToStartPerHost < 1) {
            numToStartPerHost = 1;
        }
        return numToStartPerHost;
  }

  protected NSArray<MInstance> instancesToStart(NSArray<MInstance> inactiveInstances, NSArray<MHost> activeHosts,
      int numInstancesToStartPerHost) {
    NSMutableArray<MInstance> startingInstances = new NSMutableArray<MInstance>();
        for (int i = 0; i < numInstancesToStartPerHost; i++) {
            for (MHost host : activeHosts) {
                NSArray<MInstance> inactiveInstancesForHost = MInstance.HOST.eq(host).filtered(inactiveInstances);
                if (inactiveInstancesForHost != null && inactiveInstancesForHost.count() >= i) {
                    MInstance instance = inactiveInstancesForHost.objectAtIndex(i);
                    log("Starting inactive instance " + instance.displayName() + " on host " + host.addressAsString());
                    startingInstances.addObject(instance);
                } else {
                    log("Not enough inactive instances on host: " + host.addressAsString());
                }
            }
        }
    return startingInstances.immutableClone();
  }
 
  protected boolean doAllRunningInstancesUseScheduling(NSArray<MInstance> runningInstances) {
    boolean useScheduling = true;
        for (MInstance instance : runningInstances) {
            useScheduling &= instance.schedulingEnabled() != null && instance.schedulingEnabled().booleanValue();
        }
        return useScheduling;
  }

  protected void startInstances(NSArray<MInstance> startingInstances, NSArray<MHost> activeHosts, boolean useScheduling) {
    for (MInstance instance : startingInstances) {
            if (useScheduling) {
                instance.setSchedulingEnabled(Boolean.TRUE);
            }
            instance.setAutoRecover(Boolean.TRUE);
        }
        handler().sendUpdateInstancesToWotaskds(startingInstances, activeHosts);
        handler().sendStartInstancesToWotaskds(startingInstances, activeHosts);
  }

  protected void waitForInactiveInstancesToStart(NSArray<MInstance> startingInstances, NSArray<MHost> activeHosts)
      throws InterruptedException {
    boolean waiting = true;

        // wait until apps have started
        while (waiting) {
            handler().startReading();
            try {
                log("Checking to see if inactive instances have started");
                handler().getInstanceStatusForHosts(activeHosts);
                boolean allStarted = true;
                for (MInstance instance : startingInstances) {
                    allStarted &= instance.isRunning_M();
                }
                if (allStarted) {
                    waiting = false;
                } else {
                    sleep(10 * 1000);
                }
            } finally {
                handler().endReading();
            }
        }
        log("Started inactive instances sucessfully");
  }

  protected void refuseNewSessions(NSArray<MInstance> restartingInstances, NSArray<MHost> activeHosts) {
    for (MInstance instance : restartingInstances) {
            instance.setRefusingNewSessions(true);
        }
        handler().sendRefuseSessionToWotaskds(restartingInstances, activeHosts, true);
  }
 
  protected void restartInstances(NSArray<MInstance> runningInstances, NSArray<MHost> activeHosts, boolean useScheduling)
      throws InterruptedException {
    for (MInstance instance : runningInstances) {
          NSArray<MInstance> instanceInArray = new NSArray<MInstance>(instance);
            handler().sendStopInstancesToWotaskds(instanceInArray, activeHosts);
           
            sleep(10 * 1000);
           
            handler().sendUpdateInstancesToWotaskds(instanceInArray, activeHosts);

            startInstances(instanceInArray, activeHosts, useScheduling);
            waitForInactiveInstancesToStart(instanceInArray, activeHosts);
            log("Restarted instance " + instance.displayName() + " sucessfully");
    }
  }
 
    protected void stopInstances(NSMutableArray<MInstance> stoppingInstances, NSArray<MHost> activeHosts) {
        for (MInstance instance : stoppingInstances) {
            instance.setSchedulingEnabled(Boolean.FALSE);
            instance.setAutoRecover(Boolean.FALSE);
       
        handler().sendUpdateInstancesToWotaskds(stoppingInstances, activeHosts);
        handler().sendStopInstancesToWotaskds(stoppingInstances, activeHosts);
        log("Stopped instances " + stoppingInstances.toString() + " sucessfully");
  }
 
}
TOP

Related Classes of com.webobjects.monitor.application.starter.RollingShutdownBouncer

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.