package org.radargun.state;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.radargun.DistStage;
import org.radargun.DistStageAck;
import org.radargun.MasterStage;
import org.radargun.Stage;
import org.radargun.config.FixedSizeBenchmarkConfig;
import org.radargun.config.MasterConfig;
import org.radargun.utils.Utils;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

/**
 * State residing on the server, passed to each stage before execution.
 *
 * @author Mircea.Markus@jboss.com
 */
public class MasterState extends StateBase {

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

   private MasterConfig config;
   private List<FixedSizeBenchmarkConfig> benchmarks;
   private FixedSizeBenchmarkConfig currentBenchmark;
   private long startTime = System.currentTimeMillis();
   private DistStage currentDistStage;

   public MasterState(MasterConfig config) {
      this.config = config;
      benchmarks = new ArrayList<FixedSizeBenchmarkConfig>(config.getBenchmarks());
      if (benchmarks.isEmpty())
         throw new IllegalStateException("there must be at least one benchmark");
      currentBenchmark = benchmarks.remove(0);
      logBenchmarkStarted();
   }

   public MasterConfig getConfig() {
      return config;
   }

   public DistStage getNextDistStageToProcess() {
      while (currentBenchmark.hasNextStage()) {
         Stage stage = currentBenchmark.nextStage();
         if (stage instanceof DistStage) {
            currentDistStage = (DistStage) stage;
            return currentDistStage;
         } else {
            executeServerStage((MasterStage) stage);
         }
      }
      //if we are here it means we finished executed the current benchmark and we should move to next one
      if (benchmarks.size() == 0) {
         long duration = System.currentTimeMillis() - startTime;
         String duartionStr = Utils.getDurationString(duration);
         log.info("Successfully executed all benchmarks in " + duartionStr + ", exiting.");
         return null;
      }
      currentBenchmark = benchmarks.remove(0);
      logBenchmarkStarted();
      return getNextDistStageToProcess();
   }


   public DistStage getCurrentDistStage() {
      return currentDistStage;
   }

   public int getSlavesCountForCurrentStage() {
      return currentDistStage.getActiveSlaveCount();
   }

   public boolean distStageFinished(List<DistStageAck> acks) {
      // Sort acks so that logs are more readable.
      Collections.sort(acks, new Comparator<DistStageAck>() {
         @Override
         public int compare(DistStageAck o1, DistStageAck o2) {
            int thisVal = o1.getSlaveIndex();
            int anotherVal = o2.getSlaveIndex();
            return (thisVal<anotherVal ? -1 : (thisVal==anotherVal ? 0 : 1));
         }
      });
      boolean stageOk = currentDistStage.processAckOnMaster(acks, this);
      if (stageOk) return true;
      if (!currentDistStage.isExitBenchmarkOnSlaveFailure()) {
         log.warn("Execution error for current benchmark, skipping rest of the stages");
         currentBenchmark.errorOnCurrentBenchmark();
         return true;
      } else {
         log.info("Exception error on current stage, and exiting (stage's exitBenchmarkOnSlaveFailure is set to true).");
         return false;
      }
   }

   private void executeServerStage(MasterStage servStage) {
      if (log.isDebugEnabled())
         log.debug("Starting '" + servStage.getClass().getSimpleName() + "' on master node only. Details:" + servStage);
      else
         log.info("Starting '" + servStage.getClass().getSimpleName() + "' on master node only.");
      servStage.init(this);
      try {
         if (!servStage.execute()) {
            log.warn("Issues while executing master stage: " + servStage);
         } else {
            log.trace("Master stage executed successfully " + servStage);
         }
      } catch (Exception e) {
         log.warn("Caught exception", e);
      }
   }

   public String nameOfTheCurrentBenchmark() {
      String prodName = currentBenchmark.getProductName();
      if (prodName == null) {
         throw new IllegalStateException("Null prod name not allowed!");
      }
      return prodName;
   }

   public String configNameOfTheCurrentBenchmark() {
      return currentBenchmark.getConfigName();
   }

   private void logBenchmarkStarted() {
      //this might happen in the benchmark that generates the report.GG
      if (currentBenchmark.getProductName() != null) {
         log.info("Started benchmarking product '" + currentBenchmark.getProductName() + '\'');
      }
   }
}

@@ -1169,17 +1169,17 @@
 eption(%22
-t
+T
 here mus
@@ -4243,16 +4243,19 @@
 ull prod
+uct
  name no
@@ -4455,80 +4455,8 @@
 ) %7B%0A
-      //this might happen in the benchmark that generates the report.GG%0A
     
@@ -4599,12 +4599,73 @@
 ) + 
-'%5C''
+%22' with configuration '%22 + currentBenchmark.getConfigName() + %22'%22
 );%0A 

Print config name as well as product name