package ml.dmlc.xgboost4j;



import java.io.*;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.atomic.AtomicReference;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

/**
 * Distributed RabitTracker, need to be started on driver code before running distributed jobs.
 */
public class RabitTracker {
  // Maybe per tracker logger?
  private static final Log logger = LogFactory.getLog(RabitTracker.class);
  // tracker python file.
  private static String tracker_py = null;
  // environment variable to be pased.
  private Map<String, String> envs = new HashMap<String, String>();
  // number of workers to be submitted.
  private int num_workers;
  private AtomicReference<Process> trackerProcess = new AtomicReference<Process>();

  /**
   * Tracker logger that logs output from tracker.
   */
  private class TrackerProcessLogger implements Runnable {
    public void run() {

      Log trackerProcessLogger = LogFactory.getLog(TrackerProcessLogger.class);
      BufferedReader reader = new BufferedReader(new InputStreamReader(
              trackerProcess.get().getErrorStream()));
      String line;
      try {
        while ((line = reader.readLine()) != null) {
          trackerProcessLogger.info(line);
        }
      } catch (IOException ex) {
        trackerProcessLogger.error(ex.toString());
      }
    }
  }

  private void initTrackerPy() throws IOException {
    try {
      tracker_py = NativeLibLoader.createTempFileFromResource("/tracker.py");
    } catch (IOException ioe) {
      logger.trace("cannot access tracker python script");
      throw ioe;
    }
  }


  public RabitTracker(int num_workers) {
    this.num_workers = num_workers;
  }

  /**
   * Get environments that can be used to pass to worker.
   * @return The environment settings.
   */
  public Map<String, String> getWorkerEnvs() {
    return envs;
  }

  private void loadEnvs(InputStream ins) throws IOException {
    try {
      BufferedReader reader = new BufferedReader(new InputStreamReader(ins));
      assert reader.readLine().trim().equals("DMLC_TRACKER_ENV_START");
      String line;
      while ((line = reader.readLine()) != null) {
        if (line.trim().equals("DMLC_TRACKER_ENV_END")) {
          break;
        }
        String[] sep = line.split("=");
        if (sep.length == 2) {
          envs.put(sep[0], sep[1]);
        }
      }
      reader.close();
    } catch (IOException ioe){
      logger.error("cannot get runtime configuration from tracker process");
      ioe.printStackTrace();
      throw ioe;
    }
  }

  private boolean startTrackerProcess() {
    try {
      initTrackerPy();
      trackerProcess.set(Runtime.getRuntime().exec("python " + tracker_py +
              " --num-workers=" + String.valueOf(num_workers)));
      loadEnvs(trackerProcess.get().getInputStream());
      return true;
    } catch (IOException ioe) {
      ioe.printStackTrace();
      return false;
    }
  }

  private void stop() {
    if (trackerProcess.get() != null) {
      trackerProcess.get().destroy();
    }
  }

  public boolean start() {
    if (startTrackerProcess()) {
      logger.debug("Tracker started, with env=" + envs.toString());
      // also start a tracker logger
      Thread logger_thread = new Thread(new TrackerProcessLogger());
      logger_thread.setDaemon(true);
      logger_thread.start();
      return true;
    } else {
      logger.error("FAULT: failed to start tracker process");
      stop();
      return false;
    }
  }

  public void waitFor() {
    try {
      trackerProcess.get().waitFor();
      logger.info("Tracker Process ends with exit code " + trackerProcess.get().exitValue());
      stop();
    } catch (InterruptedException e) {
      // we should not get here as RabitTracker is accessed in the main thread
      e.printStackTrace();
      logger.error("the RabitTracker thread is terminated unexpectedly");
    }
  }
}

@@ -794,16 +794,178 @@
 ss%3E();%0A%0A
+  static %7B%0A    try %7B%0A      initTrackerPy();%0A    %7D catch (IOException ex) %7B%0A      logger.error(%22load tracker library failed.%22);%0A      logger.error(ex);%0A    %7D%0A  %7D%0A%0A
   /**%0A  
@@ -1556,24 +1556,31 @@
 %0A%0A  private 
+static 
 void initTra
@@ -2818,39 +2818,16 @@
   try %7B%0A
-      initTrackerPy();%0A
       tr

change initTracker() to static