Package weka.experiment

Source Code of weka.experiment.RemoteEngine

/*
*    This program is free software; you can redistribute it and/or modify
*    it under the terms of the GNU General Public License as published by
*    the Free Software Foundation; either version 2 of the License, or
*    (at your option) any later version.
*
*    This program 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 General Public License for more details.
*
*    You should have received a copy of the GNU General Public License
*    along with this program; if not, write to the Free Software
*    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/

/*
*    RemoteEngine.java
*    Copyright (C) 2000 University of Waikato, Hamilton, New Zealand
*
*/


package weka.experiment;

import weka.core.Queue;
import weka.core.RevisionHandler;
import weka.core.RevisionUtils;

import java.net.InetAddress;
import java.net.URL;
import java.net.URLClassLoader;
import java.rmi.Naming;
import java.rmi.RMISecurityManager;
import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;
import java.util.Enumeration;
import java.util.Hashtable;

/**
* A general purpose server for executing Task objects sent via RMI.
*
* @author Mark Hall (mhall@cs.waikato.ac.nz)
* @version $Revision: 1.10 $
*/
public class RemoteEngine
  extends UnicastRemoteObject
  implements Compute, RevisionHandler {

  /** for serialization */
  private static final long serialVersionUID = -1021538162895448259L;

  /** The name of the host that this engine is started on */
  private String m_HostName = "local";

  /** A queue of waiting tasks */
  private Queue m_TaskQueue = new Queue();

  /** A queue of corresponding ID's for tasks */
  private Queue m_TaskIdQueue = new Queue();

  /** A hashtable of experiment status */
  private Hashtable m_TaskStatus = new Hashtable();

  /** Is there a task running */
  private boolean m_TaskRunning = false;

  /**
   * Constructor
   * @param hostName name of the host
   * @exception RemoteException if something goes wrong
   */
  public RemoteEngine(String hostName) throws RemoteException {
    super();
    m_HostName = hostName;

    /* launch a clean-up thread. Will purge any failed or finished
       tasks still in the TaskStatus hashtable after an hour */
      
    Thread cleanUpThread;
    cleanUpThread = new Thread() {
  public void run() {
    while (true) {
      try {
        // sleep for an hour
        Thread.sleep(3600000);
      } catch (InterruptedException ie) {}

      if (m_TaskStatus.size() > 0) {
        purge();
      } else {
        System.err.println("RemoteEngine : purge - no tasks to check.");
      }
    }
  }
      };
    cleanUpThread.setPriority(Thread.MIN_PRIORITY);
    cleanUpThread.start();
  }
 
  /**
   * Takes a task object and queues it for execution
   * @param t the Task object to execute
   * @return an identifier for the Task that can be used when querying
   * Task status
   */
  public synchronized Object executeTask(Task t) throws RemoteException {
    String taskId = ""+System.currentTimeMillis()+":";
    taskId += t.hashCode();
    addTaskToQueue(t, taskId);

    return taskId;
    //    return t.execute();
  }

  /**
   * Returns status information on a particular task
   *
   * @param taskId the ID of the task to check
   * @return a <code>TaskStatusInfo</code> encapsulating task status info
   * @exception Exception if an error occurs
   */
  public Object checkStatus(Object taskId) throws Exception {
   
    TaskStatusInfo inf = (TaskStatusInfo)m_TaskStatus.get(taskId);

    if (inf == null) {
      throw new Exception("RemoteEngine ("+m_HostName+") : Task not found.");
    }
   
    TaskStatusInfo result = new TaskStatusInfo();
    result.setExecutionStatus(inf.getExecutionStatus());
    result.setStatusMessage(inf.getStatusMessage());
    result.setTaskResult(inf.getTaskResult());

    if (inf.getExecutionStatus() == TaskStatusInfo.FINISHED ||
  inf.getExecutionStatus() == TaskStatusInfo.FAILED) {
      System.err.println("Finished/failed Task id : "
       + taskId + " checked by client. Removing.");
      inf.setTaskResult(null);
      inf = null;
      m_TaskStatus.remove(taskId);
    }
    inf = null;
    return result;
  }

  /**
   * Adds a new task to the queue.
   *
   * @param t a <code>Task</code> value to be added
   * @param taskId the id of the task to be added
   */
  private synchronized void addTaskToQueue(Task t, String taskId) {
    TaskStatusInfo newTask = t.getTaskStatus();
    if (newTask == null) {
      newTask = new TaskStatusInfo();
    }
    m_TaskQueue.push(t);
    m_TaskIdQueue.push(taskId);
    newTask.setStatusMessage("RemoteEngine ("
           +m_HostName
           +") : task queued at postion: "
           +m_TaskQueue.size());
    // add task status to HashTable
    m_TaskStatus.put(taskId, newTask);
    System.err.println("Task id : " + taskId + "Queued.");
    if (m_TaskRunning == false) {
      startTask();
    }
  }

  /**
   * Checks to see if there are any waiting tasks, and if no task is
   * currently running starts a waiting task.
   */
  private void startTask() {

    if (m_TaskRunning == false && m_TaskQueue.size() > 0) {
      Thread activeTaskThread;
      activeTaskThread = new Thread() {
    public void run() {
      m_TaskRunning = true;
      Task currentTask = (Task)m_TaskQueue.pop();
      String taskId = (String)m_TaskIdQueue.pop();
      TaskStatusInfo tsi = (TaskStatusInfo)m_TaskStatus.get(taskId);
      tsi.setExecutionStatus(TaskStatusInfo.PROCESSING);
      tsi.setStatusMessage("RemoteEngine ("
         +m_HostName
         +") : task running...");
      try {
        System.err.println("Launching task id : "
         + taskId + "...");
        currentTask.execute();
        TaskStatusInfo runStatus = currentTask.getTaskStatus();
        tsi.setExecutionStatus(runStatus.getExecutionStatus());
        tsi.setStatusMessage("RemoteExperiment ("
           +m_HostName+") "
           +runStatus.getStatusMessage());
        tsi.setTaskResult(runStatus.getTaskResult());
      } catch (Exception ex) {
        tsi.setExecutionStatus(TaskStatusInfo.FAILED);
        tsi.setStatusMessage("RemoteEngine ("
           +m_HostName
           +") : task failed.");
        System.err.println("Task id " + taskId + "Failed!");
      } finally {
        if (m_TaskStatus.size() == 0) {
    purgeClasses();
        }
        m_TaskRunning = false;
        // start any waiting tasks
        startTask();
      }
    }
  };
      activeTaskThread.setPriority(Thread.MIN_PRIORITY);
      activeTaskThread.start();
    }
  }

  /**
   * Attempts to purge class types from the virtual machine. May take some
   * time as it relies on garbage collection
   */
  private void purgeClasses() {
    try {
      // see if we can purge classes
      ClassLoader prevCl =
  Thread.currentThread().getContextClassLoader();
      ClassLoader urlCl =
  URLClassLoader.newInstance(new URL[] {new URL("file:.")}, prevCl);
      Thread.currentThread().setContextClassLoader(urlCl);
    } catch (Exception ex) {
      ex.printStackTrace();
    }
  }
 
  /**
   * Checks the hash table for failed/finished tasks. Any that have been
   * around for an hour or more are removed. Clients are expected to check
   * on the status of their remote tasks. Checking on the status of a
   * finished/failed task will remove it from the hash table, therefore
   * any failed/finished tasks left lying around for more than an hour
   * suggest that their client has died..
   *
   */
  private void purge() {
    Enumeration keys = m_TaskStatus.keys();
    long currentTime = System.currentTimeMillis();
    System.err.println("RemoteEngine purge. Current time : " + currentTime);
    while (keys.hasMoreElements()) {
      String tk = (String)keys.nextElement();
      System.err.print("Examining task id : " + tk + "...");
      String timeString = tk.substring(0, tk.indexOf(':'));
      long ts = Long.valueOf(timeString).longValue();
      if (currentTime - ts > 3600000) {
  TaskStatusInfo tsi = null;
  tsi = (TaskStatusInfo)m_TaskStatus.get(tsi);
  if ((tsi != null)
      && (tsi.getExecutionStatus() == TaskStatusInfo.FINISHED ||
      tsi.getExecutionStatus() == TaskStatusInfo.FAILED)) {
    System.err.println("\nTask id : "
           + tk + " has gone stale. Removing.");
    m_TaskStatus.remove(tk);
    tsi.setTaskResult(null);
    tsi = null;
  }
      } else {
  System.err.println("ok.");
      }
    }
    if (m_TaskStatus.size() == 0) {
      purgeClasses();
    }
  }
 
  /**
   * Returns the revision string.
   *
   * @return    the revision
   */
  public String getRevision() {
    return RevisionUtils.extract("$Revision: 1.10 $");
  }

  /**
   * Main method. Gets address of the local host, creates a remote engine
   * object and binds it in the RMI registry. If there is no RMI registry,
   * then it tries to create one with default port 1099.
   *
   * @param args
   */
  public static void main(String[] args) {
    if (System.getSecurityManager() == null) {
      System.setSecurityManager(new RMISecurityManager());
    }
    InetAddress localhost = null;
    try {
      localhost = InetAddress.getLocalHost();
      System.err.println("Host name : "+localhost.getHostName());
    } catch (Exception ex) {
      ex.printStackTrace();
    }
    String name;
    if (localhost != null) {
      name = "//"+localhost.getHostName()+"/RemoteEngine";
    } else {
      name = "//localhost/RemoteEngine";
    }
   
    try {
      Compute engine = new RemoteEngine(name);
      Naming.rebind(name, engine);
      System.out.println("RemoteEngine bound in RMI registry");
    } catch (Exception e) {
      System.err.println("RemoteEngine exception: " +
       e.getMessage());
      // try to bootstrap a new registry
      try {
  System.err.println("Attempting to start rmi registry...");
  java.rmi.registry.LocateRegistry.createRegistry(1099);
  Compute engine = new RemoteEngine(name);
  Naming.rebind(name, engine);
  System.out.println("RemoteEngine bound in RMI registry");
      } catch (Exception ex) {
  ex.printStackTrace();
      }
    }
  }
}
TOP

Related Classes of weka.experiment.RemoteEngine

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.