Package com.sun.grid.jgrid.server

Source Code of com.sun.grid.jgrid.server.JCEPHandler

/*************************************************************************
*
*  The Contents of this file are made available subject to the terms of
*  the Sun Industry Standards Source License Version 1.2
*
*  Sun Microsystems Inc., March, 2001
*
*
*  Sun Industry Standards Source License Version 1.2
*  =================================================
*  The contents of this file are subject to the Sun Industry Standards
*  Source License Version 1.2 (the "License"); You may not use this file
*  except in compliance with the License. You may obtain a copy of the
*  License at http://gridengine.sunsource.net/Gridengine_SISSL_license.html
*
*  Software provided under this License is provided on an "AS IS" basis,
*  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
*  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
*  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
*  See the License for the specific provisions governing your rights and
*  obligations concerning the Software.
*
*   The Initial Developer of the Original Code is: Sun Microsystems, Inc.
*
*   Copyright: 2001 by Sun Microsystems, Inc.
*
*   All Rights Reserved.
*
************************************************************************/
/*
* JCEPHandler.java
*
* Created on May 16, 2003, 10:54 AM
*/

package com.sun.grid.jgrid.server;

import java.io.IOException;
import java.io.InterruptedIOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.rmi.NotBoundException;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.logging.*;

import com.sun.grid.jgrid.Job;
import com.sun.grid.jgrid.JobCanceledException;
import com.sun.grid.jgrid.LogListener;
import com.sun.grid.jgrid.NotInterruptableException;
import com.sun.grid.jgrid.proxy.ResultChannel;

/** The JCEPHandler handles all JCEP communications.  The main method listens for
* incoming socket requests and spins off a new thread to handle each.  The new
* thread runs an instance of JCEPHandler which them gets a JCEPProtocolModule
* to handle the socket communications.  When a client makes a request, the
* JCEPProtocolModule forwards the request to the JCEPHandler, which them
* performs the requested action.
* @author dan.templeton@sun.com
* @version 1.8
* @since 0.2
*/
public class JCEPHandler implements JCEPListener, LogListener {
  /** The default registry host to use if none is specified on the command line */ 
  private static final String REGISTRY_HOST = "localhost";
  /** The default registry port to use if none is specified on the command line */ 
  private static final int REGISTRY_PORT = ResultChannel.PORT;
  /** The default amount of number of miliseconds to wait for jobs to complete
   * after a shutdown before explicitly exiting the VM. */
  private static final long GRACE_PERIOD = 30*1000;
  /** The usage information String */ 
  private static final String USAGE =
    "Usage: java -Djava.rmi.server.codebase=codebase " +
    "com.sun.grid.jgrid.server.JCEPHandler ([-port port] " +
    "[-regport port] [-reghost host] [-grace sec] [-debug]) | [-help]";
  /** A Map of running and completed Jobs */ 
  private static Map jobMap = null;
  /** The thread running the main() method.  Used to interrupt the server on a
   * shutdown command.
   */ 
  private static Thread mainThread = null;
  /** The ResultChannel retreived from the registry server to be used for returning
   * results
   */ 
  private static ResultChannel resultChannel = null;
  /** Whether debug messages should be printed */ 
  private static boolean debug = false;
  /** The hostname for the RMI lookup server */ 
  private static String registryHost = REGISTRY_HOST;
  /** The port number for the RMI lookup server */ 
  private static int registryPort = REGISTRY_PORT;
  /** The port number on which to listen for incoming requests */ 
  private static int port = JCEP.PORT;
  /** The logging mechanism */ 
  private static Logger log = null;
  /** The amount of time to wait for jobs to complete after a shutdown before
   * explicitly exiting the VM. */
  private static long gracePeriod = GRACE_PERIOD;
  /** The number of running jobs in this engine */
  private static int numberOfRunningJobs = 0;
  /** The JCEPProtocolModule which is handling the client communications */ 
  private JCEPProtocolModule connection = null;
 
  /** Creates a new instance of JCEPHandler
   * @param socket The socket connection to be used for communicating with the client
   * @throws IOException Thrown when an error occurs while establishing a client connection
   */
  private JCEPHandler (Socket socket) throws IOException {
    connection = JCEPProtocolModule.establishConnection (this, socket);
    connection.startConnection ();
  }
 
  /** Starts up the server, which listens for incoming socket connections.
   * @param args The command line arguments
   * @throws Exception Thrown when something goes wrong.  This is a bad thing and should be fixed
   * before turning this loose on the public.
   */
  public static void main (String[] args) throws Exception {
    prepareLogging ();
    processArguments (args);
    Runtime.getRuntime ().addShutdownHook (new LogFlusher ());
   
    log.log (Level.FINER, "Starting JCEPHandler");

    jobMap = new HashMap ();
    mainThread = Thread.currentThread ();
   
    try {
      connectToResultChannel ();
    }
    catch (RemoteException e) {
      System.err.println ("Unable to connect to the result channel.");
      System.err.println ("Please make sure the compute proxy is running.");
     
      System.exit (1);
    }
   
    log.log (Level.FINEST, "Creating server socket");
   
    ServerSocket incoming = new ServerSocket (JCEP.PORT);
   
    log.log (Level.FINEST, "Accepting connections");
   
    System.out.println ("Ready");
   
    while (true) {
      Socket socket = null;
     
      try {
        socket = incoming.accept ();
      }
      catch (InterruptedIOException e) {
        log.log (Level.FINER, "Shutting down");

        break;
      }
     
      log.log (Level.FINEST, "Connection accepted");
     
      new JCEPHandler (socket);
    }
   
    /*I break this out to its own local variable so that the number doesn't
     * change between the if and the log entry. */
    int numJobs = getNumberOfJobs ();
   
    if (numJobs > 0) {
      /** This routine waits for a given amount of time and then exits the VM
       * explicitly.  This is to prevent jobs that claim to be interruptable but
       * are not from making the engine hang indefinitely. */
      log.finest ("Number of jobs still in engine: " + numJobs);
      log.finer ("Main thread beginning grace period");

      try {
        Thread.sleep (gracePeriod);
      }
      catch (InterruptedException e) {
        /* Since this grace period is rather optional, if we get interrupted
         * just go ahead and exit. */
        log.finest ("Main thread interrupted");
      }

      log.finer ("Main thread finished grace period; exiting VM");
    }
   
    System.exit (0);
  }
 
  /** Parses the command line arguments and acts accordingly
   * @param args The command line arguments
   */ 
  private static void processArguments (String[] args) {
    log.entering ("com.sun.grid.jgrid.server.JCEPHandler", "processArguments");
   
    int count = 0;
    String error = null;
   
    while (count < args.length) {
      if (args[count].equals ("-help")) {
        System.out.println (USAGE);
        System.out.println ("\t-port = port number for this server");
        System.out.println ("\t-reghost = hostname of the RMI registry");
        System.out.println ("\t-regport = port number of the RMI registry");
        System.out.println ("\t-grace = number of seconds to wait for jobs to complete");
        System.out.println ("\t-debug = turn on debuging output");
        System.out.println ("\t-help = print this message");
        System.out.println ("");
       
        System.exit (0);
      }
      else if (args[count].equals ("-debug")) {
        count++;
        debug = true;
       
        Handler ha = new StreamHandler (System.out, new SimpleFormatter ());
       
        log.addHandler (ha);
        ha.setLevel (Level.ALL);
        log.setLevel (Level.ALL);
       
        log.log (Level.CONFIG, "Debugging enabled");
      }
      else if (args[count].equals ("-reghost")) {
        count++;
       
        if (count < args.length) {
          registryHost = args[count++];
       
          log.log (Level.CONFIG, "Registry server hostname set to " + registryHost);
        }
        else {
          error = "Must specify a registry server host name";
          break;
        }
      }
      else if (args[count].equals ("-regport")) {
        count++;
       
        if (count < args.length) {
          try {
            registryPort = Integer.parseInt (args[count++]);
       
            log.log (Level.CONFIG, "Registry server port set to " + registryPort);
          }
          catch (NumberFormatException e) {
            error = "Invalid registry server port number";
            break;
          }
        }
        else {
          error = "Must specify a registry server port number";
          break;
        }
      }
      else if (args[count].equals ("-port")) {
        count++;
       
        if (count < args.length) {
          try {
            port = Integer.parseInt (args[count++]);

            log.log (Level.CONFIG, "Server port number set to " + port);
          }
          catch (NumberFormatException e) {
            error = "Invalid server port number";
            break;
          }
        }
        else {
          error = "Must specify a server port number";
          break;
        }
      }
      else if (args[count].equals ("-grace")) {
        int graceSeconds = -1;
        count++;
       
        if (count < args.length) {
          try {
            graceSeconds = Integer.parseInt (args[count++]);
          }
          catch (NumberFormatException e) {
            error = "Invalid grace period";
            break;
          }
         
          gracePeriod = (long)graceSeconds * 1000L;

          log.log (Level.CONFIG, "Grace period set to " + graceSeconds + " seconds");
        }
      }
      else {
        error = "Invalid command";
        break;
      }
    }
   
    if (error != null) {
      System.err.println (error);
      System.err.println (USAGE);
      System.exit (1);
    }
   
    log.exiting ("com.sun.grid.jgrid.server.JCEPHandler", "processArguments");
  }
 
  /** This method sets up the Logger object
   */ 
  private static void prepareLogging () {
    log = Logger.getLogger ("com.sun.grid.jgrid.server.ComputeEngine");
    log.setUseParentHandlers (false);
   
    ConsoleHandler ha = new ConsoleHandler ();
    ha.setFormatter (new Formatter () {
      public String format (LogRecord record) {
        return formatMessage (record) + "\n";
      }
    });

    log.addHandler (ha);
    ha.setLevel (Level.INFO);
    log.setLevel (Level.INFO);
  }
 
  /** Register this JCEPHandler to receive messages from an executing Job.  Called by
   * the JCEPProtocolModule.
   * @see com.sun.grid.jgrid.Logger
   * @see com.sun.grid.jgrid.Job
   * @param jobId The id of the Job to which to attach
   * @throws CommandFailedException thrown if this method cannot complete its task due to errors or failures
   */ 
  public void register (String jobId) throws CommandFailedException {
    log.entering ("com.sun.grid.jgrid.server.JCEPHandler", "register");

    Job job = (Job)jobMap.get (jobId);
   
    if (job == null) {
      log.finer ("Register command failed for job " + jobId + ": No such job");
     
      throw new CommandFailedException (jobId, "No such job");
    }
    else if (job.getState () == Job.RUNNING) {
      job.getLogger ().registerHandler (this);
   
      log.fine ("Connection has been registered with job: " + jobId);
    }
    else {
      log.finer ("Register command failed for job " + jobId + ": Job is not currently running");
     
      throw new CommandFailedException (jobId, "Job is not currently running");
    }
   
    log.exiting ("com.sun.grid.jgrid.server.JCEPHandler", "register");
  }
 
  /** Unregister for messages from a Job.  This method may be used to detach from
   * Jobs that are no longer running.  Called by the JCEPProtocolModule.
   * @see #register(String)
   * @param jobId The id of the Job from which to detach
   * @throws CommandFailedException thrown if this method cannot complete its task due to errors or failures
   */ 
  public void unregister (String jobId) throws CommandFailedException {
    log.entering ("com.sun.grid.jgrid.server.JCEPHandler", "unregister");
   
    Job job = (Job)jobMap.get (jobId);
   
    if (job == null) {
      log.finer ("Unegister command failed for job " + jobId + ": No such job");
     
      throw new CommandFailedException (jobId, "No such job");
    }
    else {
      job.getLogger ().unregisterHandler (this);
   
      log.fine ("Connection has been unregistered with job: " + jobId);
    }

    log.exiting ("com.sun.grid.jgrid.server.JCEPHandler", "unregister");
  }
 
  /** Cancel the executing Job.  This is done by calling the Job.cancel() method.
   * If the Job cannot be canceled, either because it is no longer executing or it is
   * uninterruptable this method will notify the client by throwing a
   * CommandFailedException.
   * @see com.sun.grid.jgrid.Job#cancel()
   * @param jobId The id of the Job to cancel
   * @throws CommandFailedException thrown if this method cannot complete its task due to errors or failures
   */ 
  public void cancelJob (String jobId) throws CommandFailedException {
    log.entering ("com.sun.grid.jgrid.server.JCEPHandler", "cancelJob");
   
    Job job = (Job)jobMap.get (jobId);
   
    if (job == null) {
      log.finer ("Cancel command failed for job " + jobId + ": No such job");
     
      throw new CommandFailedException (jobId, "No such job");
    }
    else if (job.getState () == Job.RUNNING) {
      try {
        job.cancel ();
   
        log.fine ("Job has been canceled: " + jobId);
      }
      catch (NotInterruptableException e) {
        log.finer ("Cancel command failed for job " + jobId + ": Job cannot be interrupted");
     
        throw new CommandFailedException (jobId, "Job cannot be interrupted");
      }
    }
    else {
      log.finer ("Cancel command failed for job " + jobId + ": Job is not currently running");
     
      throw new CommandFailedException (jobId, "Job is not currently running");
    }
   
    log.exiting ("com.sun.grid.jgrid.server.JCEPHandler", "cancelJob");
  }
 
  /** Checkpoint the executing Job.  This is done by calling the Job.checkpoint()
   * method.
   * If the Job cannot be checkpointed, either because it is no longer executing or
   * it is uninterruptable this method will notify the client by throwing a
   * CommandFailedException.
   * Called by the JCEPProtocolModule.
   * @see com.sun.grid.jgrid.Job#checkpoint()
   * @param jobId The id of the job to checkpoint
   * @throws CommandFailedException thrown if this method cannot complete its task due to errors or failures
   */ 
  public void checkpoint (String jobId) throws CommandFailedException {
    log.entering ("com.sun.grid.jgrid.server.JCEPHandler", "checkpoint");
   
    Job job = (Job)jobMap.get (jobId);
   
    if (job == null) {
      log.finer ("Checkpoint command failed for job " + jobId + ": No such job");
     
      throw new CommandFailedException (jobId, "No such job");
    }
    else if (job.getState () == Job.RUNNING) {
      try {
        job.checkpoint ();
       
        log.fine ("Job has been checkpointed: " + jobId);
      }
      catch (NotInterruptableException e) {
        log.finer ("Checkpoint command failed for job " + jobId + ": Job cannot be interrupted");
       
        throw new CommandFailedException (jobId, "Job cannot be interrupted");
      }
    }
    else {
      log.finer ("Checkpoint command failed for job " + jobId + ": Job is not currently running");
     
      throw new CommandFailedException (jobId, "Job is not currently running");
    }
   
    log.exiting ("com.sun.grid.jgrid.server.JCEPHandler", "checkpoint");
  }
 
  /** Shutdown the JCEP server.  All Jobs are first checkpointed and then canceled.
   * Called by JCEPProtocolModule.
   * @see com.sun.grid.jgrid.Job#cancel()
   * @see com.sun.grid.jgrid.Job#checkpoint()
   */ 
  public void shutdown () {
    log.entering ("com.sun.grid.jgrid.server.JCEPHandler", "shutdown");
 
    String jobId = null;
    Iterator i = jobMap.keySet ().iterator ();
   
    while (i.hasNext ()) {
      jobId = (String)i.next ();
      Job job = (Job)jobMap.get (jobId);
 
      /* Every job will be canceled if possible.  Jobs that aren't interruptable
       * or that don't complete before the grace period is over will be stopped
       * prematurely by the VM exit. */
      if (job.getState () == job.RUNNING) {
        try {
          job.cancel ();
        }
        catch (NotInterruptableException e) {
          this.logError (jobId, "Job cannot be interrupted");
        }
      }
    }
   
    try {
      connection.notifyShutdown ();
      connection.closeConnection ();
    }
    catch (IOException e) {
      e.printStackTrace ();
    }
   
    mainThread.interrupt ();
   
    log.exiting ("com.sun.grid.jgrid.server.JCEPHandler", "shutdown");
  }
 
  /** Submit a Job for execution.  A new thread will be created for the Job, and the
   * Job object will be stored in the Job Map.  Called by JCEPProtocolModule.
   * @param job A Job object representing the job to be executed
   */ 
  public void submitJob (Job job) {
    log.entering ("com.sun.grid.jgrid.server.JCEPHandler", "submitJob");
   
    com.sun.grid.jgrid.Logger logger = new com.sun.grid.jgrid.Logger (job.getJobId ());
   
    logger.registerHandler (this);
    job.setLogger (logger);
   
    Thread computeThread = new Thread (job);

    jobMap.put (job.getJobId (), job);
   
    computeThread.start ();
   
    incrementNumberOfJobs ();
    log.exiting ("com.sun.grid.jgrid.server.JCEPHandler", "submitJob");
  }

  /** An error has occured in an executing job.  The error is communicated to the
   * client via JCEPProtocolModule.logError().  Called by Logger.
   * @param jobId The id of the Job from which the error originated
   * @param error A String describing the error
   * @see com.sun.grid.jgrid.server.JCEPProtocolModule#logError(String, String)
   * @see com.sun.grid.jgrid.Logger
   */ 
  public void logError (String jobId, String error) {
    log.entering ("com.sun.grid.jgrid.server.JCEPHandler", "logError");
   
    try {
      connection.logError (jobId, error);
    }
    catch (IOException e) {
      /* Our channel is dead, so just use the log file */
      log.warning ("Unable to log error for job " + jobId + ": " + error);
      log.warning ("Problem caused by IOException:" + com.sun.grid.jgrid.Logger.getExceptionAsString (e));
    }
   
    log.exiting ("com.sun.grid.jgrid.server.JCEPHandler", "logError");
  }

  /** An executing Job has sent a message.  The message is communicated to the client
   * via JCEPProtocolModule.logMessage().  Called by Logger.
   * @param jobId The id of the Job from which the message originated
   * @param message The text of the message
   * @see com.sun.grid.jgrid.server.JCEPProtocolModule#logMessage(String, String)
   * @see com.sun.grid.jgrid.Logger
   */ 
  public void logMessage (String jobId, String message) {
    log.entering ("com.sun.grid.jgrid.server.JCEPHandler", "logMessage");
   
    try {
      connection.logMessage (jobId, message);
    }
    catch (IOException e) {
      /* Our channel is dead, so just use the log file */
      log.warning ("Unable to log message for job " + jobId + ": " + message);
      log.warning ("Problem caused by IOException:" + com.sun.grid.jgrid.Logger.getExceptionAsString (e));
    }
   
    log.exiting ("com.sun.grid.jgrid.server.JCEPHandler", "logMessage");
  }

  /** An executing Job has exited abnormally by being canceled .
   * The client is notified of the state change via
   * JCEPProtocolModule.notifyJobStopped().  Called by Logger.
   * @param jobId The id of the Job which exited
   * @see com.sun.grid.jgrid.server.JCEPProtocolModule#notifyJobStopped(String)
   * @see com.sun.grid.jgrid.Logger
   */ 
  public void notifyJobStopped (String jobId) {
    log.entering ("com.sun.grid.jgrid.server.JCEPHandler", "notifyJobStopped");
   
    try {
      connection.notifyJobStopped (jobId);
    }
    catch (IOException e) {
      /* Our channel is dead, so just use the log file */
      log.warning ("Unable to notify that job has exited: " + jobId);
      log.warning ("Problem caused by IOException:" + com.sun.grid.jgrid.Logger.getExceptionAsString (e));
    }
   
    Job job = (Job)jobMap.get (jobId);
   
    if (job == null) {
      log.severe ("Job " + jobId + " has exited but no longer exists in the job map");
    }
    else {
      try {
        resultChannel.sendException (new JobCanceledException (), jobId);
      }
      catch (RemoteException e) {
        this.logError (jobId, "Unable to sends results of job to result channel");
      }
    }
   
    decrementNumberOfJobs ();
   
    log.exiting ("com.sun.grid.jgrid.server.JCEPHandler", "notifyJobStopped");
  }

  /** An executing Job has exited abnormally by
   * throwing an Exception.  The client is notified of the state change via
   * JCEPProtocolModule.notifyJobFailed().  Called by Logger.
   * @param jobId The id of the Job which exited
   * @see com.sun.grid.jgrid.server.JCEPProtocolModule#notifyJobFailed(String)
   * @see com.sun.grid.jgrid.Logger
   */ 
  public void notifyJobFailed (String jobId) {
    log.entering ("com.sun.grid.jgrid.server.JCEPHandler", "notifyJobExited");
   
    try {
      connection.notifyJobFailed (jobId);
    }
    catch (IOException e) {
      /* Our channel is dead, so just use the log file */
      log.warning ("Unable to notify that job has exited: " + jobId);
      log.warning ("Problem caused by IOException:" + com.sun.grid.jgrid.Logger.getExceptionAsString (e));
    }
   
    Job job = (Job)jobMap.get (jobId);
   
    if (job == null) {
      log.severe ("Job " + jobId + " has exited but no longer exists in the job map");
    }
    else {
      Exception ex = null;
     
      try {
        resultChannel.sendException ((Exception)job.getResult (), jobId);
      }
      catch (RemoteException e) {
        this.logError (jobId, "Unable to sends results of job to result channel");
      }
    }
   
    decrementNumberOfJobs ();
   
    log.exiting ("com.sun.grid.jgrid.server.JCEPHandler", "notifyJobFailed");
  }
 
  /** An executing Job has been checkpointed.  The information is communicated to the
   * client via JCEPProtocolModule.notifyJobCheckpointed().  Called by Logger.
   * @param jobId The id of the Job which has been checkpointed
   * @see com.sun.grid.jgrid.server.JCEPProtocolModule#notifyJobCheckpointed(String)
   * @see com.sun.grid.jgrid.Logger
   */ 
  public void notifyJobCheckpointed (String jobId) {
    log.entering ("com.sun.grid.jgrid.server.JCEPHandler", "notifyJobCheckpointed");
   
    try {
      connection.notifyJobCheckpointed (jobId);
    }
    catch (IOException e) {
      /* Our channel is dead, so just use the log file */
      log.warning ("Unable to notify that job has been checkpointed: " + jobId);
      log.warning ("Problem caused by IOException:" + com.sun.grid.jgrid.Logger.getExceptionAsString (e));
    }
   
    log.exiting ("com.sun.grid.jgrid.server.JCEPHandler", "notifyJobCheckpointed");
  }
 
  /** An executing Job has been suspended.  The information is communicated to the
   * client via JCEPProtocolModule.notifyJobSuspended().  Called by Logger.
   * @param jobId The id of the Job which has been suspended
   * @see com.sun.grid.jgrid.server.JCEPProtocolModule#notifyJobSuspended(String)
   * @see com.sun.grid.jgrid.Logger
   */ 
  public void notifyJobSuspended (String jobId) {
    log.entering ("com.sun.grid.jgrid.server.JCEPHandler", "notifyJobSuspended");
   
    try {
      connection.notifyJobSuspended (jobId);
    }
    catch (IOException e) {
      /* Our channel is dead, so just use the log file */
      log.warning ("Unable to notify that job has been suspended: " + jobId);
      log.warning ("Problem caused by IOException:" + com.sun.grid.jgrid.Logger.getExceptionAsString (e));
    }
   
    log.exiting ("com.sun.grid.jgrid.server.JCEPHandler", "notifyJobSuspended");
  }
 
  /** An executing Job has been resumed.  The information is communicated to the
   * client via JCEPProtocolModule.notifyJobResumed().  Called by Logger.
   * @param jobId The id of the Job which has been resumed
   * @see com.sun.grid.jgrid.server.JCEPProtocolModule#notifyJobResumed(String)
   * @see com.sun.grid.jgrid.Logger
   */ 
  public void notifyJobResumed (String jobId) {
    log.entering ("com.sun.grid.jgrid.server.JCEPHandler", "notifyJobResumed");
   
    try {
      connection.notifyJobResumed (jobId);
    }
    catch (IOException e) {
      /* Our channel is dead, so just use the log file */
      log.warning ("Unable to notify that job has been resumed: " + jobId);
      log.warning ("Problem caused by IOException:" + com.sun.grid.jgrid.Logger.getExceptionAsString (e));
    }
   
    log.exiting ("com.sun.grid.jgrid.server.JCEPHandler", "notifyJobResumed");
  }
 
  /** An executing Job has completed normally.  The client is notified of the state
   * change via JCEPProtocolModule.notifyJobCompleted().  Called by Logger.
   * @param jobId The id of the Job which has completed
   * @see com.sun.grid.jgrid.server.JCEPProtocolModule#notifyJobCompleted(String)
   * @see com.sun.grid.jgrid.Logger
   */ 
  public void notifyJobCompleted (String jobId) {
    log.entering ("com.sun.grid.jgrid.server.JCEPHandler", "notifyJobCompleted");
   
    try {
      connection.notifyJobCompleted (jobId);
    }
    catch (IOException e) {
      /* Our channel is dead, so just use the log file */
      log.warning ("Unable to notify that job has completed: " + jobId);
      log.warning ("Problem caused by IOException:" + com.sun.grid.jgrid.Logger.getExceptionAsString (e));
    }
   
    Job job = (Job)jobMap.get (jobId);
   
    if (job == null) {
      log.severe ("Job " + jobId + " has completed but no longer exists in the job map");
    }
    else {
      try {
        resultChannel.sendResult (job.getResult (), jobId);
      }
      catch (RemoteException e) {
        this.logError (jobId, "Unable to sends results of job to result channel");
      }
    }
       
    decrementNumberOfJobs ();
   
    log.exiting ("com.sun.grid.jgrid.server.JCEPHandler", "notifyJobCompleted");
  }
 
  /** A Job has begun execution.  The client is notified of the state change via
   * JCEPProtocolModule.notifyJobStarted().  Called by Logger.
   * @param jobId The id of the Job which has started execution
   * @see com.sun.grid.jgrid.server.JCEPProtocolModule#notifyJobStarted(String)
   * @see com.sun.grid.jgrid.Logger
   */ 
  public void notifyJobStarted (String jobId) {
    log.entering ("com.sun.grid.jgrid.server.JCEPHandler", "notifyJobStarted");
    try {
      connection.notifyJobStarted (jobId);
    }
    catch (IOException e) {
      /* Our channel is dead, so just use the log file */
      log.warning ("Unable to notify that job has been started: " + jobId);
      log.warning ("Problem caused by IOException:" + com.sun.grid.jgrid.Logger.getExceptionAsString (e));
    }
   
    log.exiting ("com.sun.grid.jgrid.server.JCEPHandler", "notifyJobStarted");
  }
 
  /** This method retrieves the ResultChannel object from the RMI registry server.
   * @throws RemoteException if an error occurs while trying to retrieve the ResultChannel object
   */ 
  private static void connectToResultChannel () throws RemoteException {
    log.entering ("com.sun.grid.jgrid.server.JCEPHandler", "connectToResultChannel");
   
    Registry r = LocateRegistry.getRegistry (registryHost, registryPort);
   
    try {
      resultChannel = (ResultChannel)r.lookup (ResultChannel.LOOKUP_NAME);
    }
    catch (NotBoundException e) {
      log.throwing ("com.sun.grid.jgrid.server.JCEPHandler", "connectToResultChannel", e);
     
      throw new RemoteException ("Unable to bind to result channel", e);
    }
   
    log.exiting ("com.sun.grid.jgrid.server.JCEPHandler", "connectToResultChannel");
  }
 
  /** Increment the number of running jobs by 1 */ 
  private static synchronized void incrementNumberOfJobs () {
    numberOfRunningJobs++;
   
    log.finest ("Number of running jobs increased to " + numberOfRunningJobs);
  }
 
  /** Decrement the number of running jobs by 1 */ 
  private static synchronized void decrementNumberOfJobs () {
    numberOfRunningJobs--;
   
    log.finest ("Number of running jobs decreased to " + numberOfRunningJobs);
  }

  /** Get the number of running jobs.
   * @return the number of running jobs
   */ 
  private static synchronized int getNumberOfJobs () {
    return numberOfRunningJobs;
  }
 
  /** Flushes the logs.  Used in a shutdown hook to make sure all information gets
   * displayed in the event the server is stopped.
   */ 
  private static void flushLogs () {
    Handler[] handlers = log.getHandlers ();
   
    for (int count = 0; count < handlers.length; count++) {
      handlers[count].flush ();
    }
  }
 
  /** Resume a suspended Job
   * If the Job cannot be resume, either because it is not suspended or
   * it is uninterruptable this method will notify the client by throwing a
   * CommandFailedException.  Called by the JCEPProtocolModule.
   * @param jobId The id of the Job to resume
   * @throws CommandFailedException if the command was unable to complete sucessfully
   * @see com.sun.grid.jgrid.Job#resume()
   */ 
  public void resume (String jobId) throws CommandFailedException {
    log.entering ("com.sun.grid.jgrid.server.JCEPHandler", "resume");
   
    Job job = (Job)jobMap.get (jobId);
   
    if (job == null) {
      log.finer ("Resume command failed for job " + jobId + ": No such job");
     
      throw new CommandFailedException (jobId, "No such job");
    }
    else if (job.getState () == Job.SUSPENDED) {
      job.resume ();

      log.fine ("Job has been resumed: " + jobId);
    }
    else {
      log.finer ("Resume command failed for job " + jobId + ": Job is not suspended");
     
      throw new CommandFailedException (jobId, "Job is not suspended");
    }
   
    log.exiting ("com.sun.grid.jgrid.server.JCEPHandler", "resume");
  }
 
  /** Suspend an executing Job
   * If the Job cannot be suspended, either because it is no longer executing or
   * it is uninterruptable this method will notify the client by throwing a
   * CommandFailedException. Called by the JCEPProtocolModule.
   * @param jobId The id of the Job to suspend
   * @throws CommandFailedException if the command was unable to complete sucessfully
   * @see com.sun.grid.jgrid.Job#suspend()
   */ 
  public void suspend (String jobId) throws CommandFailedException {
    log.entering ("com.sun.grid.jgrid.server.JCEPHandler", "suspend");
   
    Job job = (Job)jobMap.get (jobId);
   
    if (job == null) {
      log.finer ("Suspend command failed for job " + jobId + ": No such job");
     
      throw new CommandFailedException (jobId, "No such job");
    }
    else if (job.getState () == Job.RUNNING) {
      try {
        job.suspend ();
       
        log.fine ("Job has been suspended: " + jobId);
      }
      catch (NotInterruptableException e) {
        log.finer ("Suspend command failed for job " + jobId + ": Job cannot be interrupted");
       
        throw new CommandFailedException (jobId, "Job cannot be interrupted");
      }
    }
    else {
      log.finer ("Suspend command failed for job " + jobId + ": Job is not currently running");
     
      throw new CommandFailedException (jobId, "Job is not currently running");
    }
   
    log.exiting ("com.sun.grid.jgrid.server.JCEPHandler", "suspend");
  }
 
  /** A helper class used as a shutdown hook.  Its only purpose is to call
   * flushLogs().
   * @see com.sun.grid.jgrid.server.JCEPHandler#flushLogs()
   */ 
  private static class LogFlusher extends Thread {
    /** Used as a shutdown hook.  Its only purpose is to call flushLogs().
     * @see com.sun.grid.jgrid.server.JCEPHandler#flushLogs()
     */   
    public void run () {
      flushLogs ();
    }
  }
}
TOP

Related Classes of com.sun.grid.jgrid.server.JCEPHandler

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.