Package org.radargun

Source Code of org.radargun.Slave$ScenarioRunner

package org.radargun;

import java.io.IOException;
import java.net.InetAddress;
import java.util.HashMap;
import java.util.Map;

import org.radargun.config.Cluster;
import org.radargun.config.Configuration;
import org.radargun.config.InitHelper;
import org.radargun.config.PropertyHelper;
import org.radargun.config.Scenario;
import org.radargun.logging.Log;
import org.radargun.logging.LogFactory;
import org.radargun.reporting.Timeline;
import org.radargun.stages.ScenarioCleanupStage;
import org.radargun.state.SlaveState;
import org.radargun.traits.TraitHelper;
import org.radargun.utils.ArgsHolder;

/**
* Slave being coordinated by a single {@link Master} object in order to run benchmarks.
*
* @author Mircea Markus <Mircea.Markus@jboss.com>
*/
public class Slave {

   private static Log log = LogFactory.getLog(Slave.class);

   private SlaveState state = new SlaveState();
   private RemoteMasterConnection connection;

   private Scenario scenario;
   private Configuration configuration;
   private Cluster cluster;
   private int slaveIndex;

   public Slave(RemoteMasterConnection connection) {
      this.connection = connection;
      Runtime.getRuntime().addShutdownHook(new ShutDownHook("Slave process"));
   }

   private void run(int slaveIndex) throws Exception {
      InetAddress address = connection.connectToMaster(slaveIndex);
      // the provided slaveIndex is just a "recommendation"
      state.setSlaveIndex(this.slaveIndex = connection.receiveSlaveIndex());
      log.info("Received slave index " + state.getSlaveIndex());
      state.setMaxClusterSize(connection.receiveSlaveCount());
      log.info("Received slave count " + state.getMaxClusterSize());
      state.setLocalAddress(address);
      while (true) {
         Object object = connection.receiveObject();
         log.trace("Received " + object);
         if (object == null) {
            log.info("Master shutdown!");
            break;
         } else if (object instanceof Scenario) {
            scenario = (Scenario) object;
         } else if (object instanceof Configuration) {
            configuration = (Configuration) object;
            state.setConfigName(configuration.name);
         } else if (object instanceof Cluster) {
            cluster = (Cluster) object;
            ScenarioRunner runner = new ScenarioRunner();
            runner.start();
            runner.join();
            // we got -1, now run the cleanup
            runCleanup();
         } else if (object instanceof Timeline.Request) {
            connection.sendResponse(state.getTimeline());
         }
      }
      ShutDownHook.exit(0);
   }

   private void runCleanup() throws IOException {
      DistStageAck response = null;
      try {
         Map<String, String> extras = getCurrentExtras(configuration, cluster);
         ScenarioCleanupStage stage = (ScenarioCleanupStage) scenario.getStage(scenario.getStageCount() - 1, state, extras, null);
         InitHelper.init(stage);
         stage.initOnSlave(state);
         log.info("Starting stage " + (log.isDebugEnabled() ? stage.toString() : stage.getName()));
         response = stage.executeOnSlave();
      } catch (Exception e) {
         log.error("Stage execution has failed", e);
         response = new DistStageAck(state).error("Stage execution has failed", e);
      } finally {
         if (response == null) {
            response = new DistStageAck(state).error("Stage returned null response", null);
         }
         connection.sendResponse(response);
      }
   }

   // We have to run each service in new thread in order to prevent classloader leaking
   // through thread locals
   private class ScenarioRunner extends Thread {
      private ScenarioRunner() {
         super("sc-main");
      }

      @Override
      public void run() {
         try {
            scenarioLoop();
         } catch (IOException e) {
            log.error("Communication with master failed", e);
            e.printStackTrace();
            ShutDownHook.exit(127);
         } catch (Throwable t) {
            log.error("Unexpected error in scenario", t);
            t.printStackTrace();
            ShutDownHook.exit(127);
         }
      }
   }

   private void scenarioLoop() throws IOException {
      Cluster.Group group = cluster.getGroup(state.getSlaveIndex());
      Configuration.Setup setup = configuration.getSetup(group.name);
      state.setCluster(cluster);
      state.setPlugin(setup.plugin);
      state.setService(setup.service);
      state.setTimeline(new Timeline(slaveIndex));
      Map<String, String> extras = getCurrentExtras(configuration, cluster);
      Object service = ServiceHelper.createService(state.getClassLoader(), setup.plugin, setup.service, configuration.name, setup.file, slaveIndex, setup.getProperties(), extras);
      log.info("Service is " + service.getClass().getSimpleName() + PropertyHelper.toString(service));
      Map<Class<?>, Object> traits = TraitHelper.retrieve(service);
      state.setTraits(traits);
      for (;;) {
         int stageId = connection.receiveNextStageId();
         log.trace("Received stage ID " + stageId);
         DistStage stage = (DistStage) scenario.getStage(stageId, state, extras, null);
         if (stage instanceof ScenarioCleanupStage) {
            // this is always the last stage and is ran in main thread (not sc-main)
            break;
         }
         TraitHelper.InjectResult result = null;
         DistStageAck response;
         Exception initException = null;
         try {
            result = TraitHelper.inject(stage, traits);
            InitHelper.init(stage);
            stage.initOnSlave(state);
         } catch (Exception e) {
            log.error("Stage initialization has failed", e);
            initException = e;
         }
         if (initException != null) {
            response = new DistStageAck(state).error("Stage initialization has failed", initException);
         } else if (!stage.shouldExecute()) {
            log.info("Stage should not be executed");
            response = new DistStageAck(state);
         } else if (result == TraitHelper.InjectResult.SKIP) {
            log.info("Stage was skipped because it was missing some traits");
            response = new DistStageAck(state);
         } else if (result == TraitHelper.InjectResult.FAILURE) {
            String message = "The stage was not executed because it missed some mandatory traits.";
            log.error(message);
            response = new DistStageAck(state).error(message, null);
         } else {
            log.info("Starting stage " + (log.isDebugEnabled() ? stage.toString() : stage.getName()));
            long start = System.currentTimeMillis();
            long end;
            try {
               response = stage.executeOnSlave();
               end = System.currentTimeMillis();
               if (response == null) {
                  response = new DistStageAck(state).error("Stage returned null response", null);
               }
               log.info("Finished stage " + stage.getName());
               response.setDuration(end - start);
            } catch (Exception e) {
               end = System.currentTimeMillis();
               log.error("Stage execution has failed", e);
               response = new DistStageAck(state).error("Stage execution has failed", e);
            }
            state.getTimeline().addEvent(Stage.STAGE, new Timeline.IntervalEvent(start, stage.getName(), end - start));
         }
         connection.sendResponse(response);
      }
   }

   public static void main(String[] args) {
      ArgsHolder.init(args, ArgsHolder.ArgType.SLAVE);
      if (ArgsHolder.getMasterHost() == null) {
         ArgsHolder.printUsageAndExit(ArgsHolder.ArgType.SLAVE);
      }
      Slave slave = new Slave(new RemoteMasterConnection(ArgsHolder.getMasterHost(), ArgsHolder.getMasterPort()));
      try {
         slave.run(ArgsHolder.getSlaveIndex());
      } catch (Exception e) {
         e.printStackTrace();
         ShutDownHook.exit(127);
      }
   }

   private Map<String, String> getCurrentExtras(Configuration configuration, Cluster cluster) {
      Map<String, String> extras = new HashMap<String, String>();
      extras.put(Properties.PROPERTY_CONFIG_NAME, configuration.name);
      extras.put(Properties.PROPERTY_PLUGIN_NAME, state.getPlugin());
      extras.put(Properties.PROPERTY_CLUSTER_SIZE, String.valueOf(cluster.getSize()));
      extras.put(Properties.PROPERTY_CLUSTER_MAX_SIZE, String.valueOf(state.getMaxClusterSize()));
      extras.put(Properties.PROPERTY_SLAVE_INDEX, String.valueOf(state.getSlaveIndex()));
      Cluster.Group group = cluster.getGroup(state.getSlaveIndex());
      extras.put(Properties.PROPERTY_GROUP_NAME, group.name);
      extras.put(Properties.PROPERTY_GROUP_SIZE, String.valueOf(group.size));
      return extras;
   }
}
TOP

Related Classes of org.radargun.Slave$ScenarioRunner

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.