org/objectweb/proactive/scheduler/Communicator.java

00001 /* 
00002  * ################################################################
00003  * 
00004  * ProActive: The Java(TM) library for Parallel, Distributed, 
00005  *            Concurrent computing with Security and Mobility
00006  * 
00007  * Copyright (C) 1997-2007 INRIA/University of Nice-Sophia Antipolis
00008  * Contact: proactive@objectweb.org
00009  * 
00010  * This library is free software; you can redistribute it and/or
00011  * modify it under the terms of the GNU Lesser General Public
00012  * License as published by the Free Software Foundation; either
00013  * version 2.1 of the License, or any later version.
00014  *  
00015  * This library is distributed in the hope that it will be useful,
00016  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00017  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00018  * Lesser General Public License for more details.
00019  * 
00020  * You should have received a copy of the GNU Lesser General Public
00021  * License along with this library; if not, write to the Free Software
00022  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
00023  * USA
00024  *  
00025  *  Initial developer(s):               The ProActive Team
00026  *                        http://www.inria.fr/oasis/ProActive/contacts.html
00027  *  Contributor(s): 
00028  * 
00029  * ################################################################
00030  */ 
00031 package org.objectweb.proactive.scheduler;
00032 
00033 import java.io.BufferedReader;
00034 import java.io.File;
00035 import java.io.IOException;
00036 import java.io.InputStreamReader;
00037 import java.net.InetAddress;
00038 import java.net.UnknownHostException;
00039 import java.util.Date;
00040 import java.util.Iterator;
00041 import java.util.Vector;
00042 
00043 import org.apache.log4j.Appender;
00044 import org.apache.log4j.Layout;
00045 import org.apache.log4j.Logger;
00046 import org.apache.log4j.PatternLayout;
00047 import org.apache.log4j.RollingFileAppender;
00048 import org.apache.log4j.WriterAppender;
00049 import org.apache.log4j.nt.NTEventLogAppender;
00050 import org.objectweb.proactive.core.node.Node;
00051 import org.objectweb.proactive.core.node.NodeException;
00052 import org.objectweb.proactive.core.node.NodeInformation;
00053 import org.objectweb.proactive.core.util.log.Loggers;
00054 import org.objectweb.proactive.core.util.log.ProActiveLogger;
00055 
00056 
00064 public class Communicator {
00065     private static Logger logger = ProActiveLogger.getLogger(Loggers.SCHEDULER_COMMAND_LISTENER);
00066 
00067     /* Logging */
00068     private static final String LOG_DIR = "." + File.separator + "logs" +
00069         File.separator;
00070     private static final String MAX_SIZE = "100KB";
00071     private static final String LOG_PATTERN = "%d %c %x %m\n\n";
00072     private static WriterAppender writerAppender;
00073     private static String hostname = null;
00074 
00075     static {
00076         configureLogging();
00077     }
00078 
00079     /* These are the constants namely the commands that are used */
00080     private static final String LOG_HEADER = "[Scheduler] ";
00081     private static final String SUB_CMD = "sub";
00082     private static final String STAT_CMD = "stat";
00083     private static final String DEL_CMD = "del";
00084     private static final String NODES_CMD = "nodes";
00085     private static final String KILL_CMD = "kill";
00086     private static final String EXIT_CMD = "exit";
00087     private static final String SUB_PROTO = SUB_CMD + " XMLDescriptorOfTheJob";
00088     private static final String STAT_PROTO = STAT_CMD + " [jobId]";
00089     private static final String DEL_PROTO = DEL_CMD + " jobId";
00090     private static final String NODES_PROTO = NODES_CMD + " [nodeURL]";
00091     private static final String KILL_PROTO = KILL_CMD;
00092     private static final String EXIT_PROTO = EXIT_CMD;
00093     private Scheduler scheduler;
00094 
00100     public Communicator(String schedulerURL) {
00101         try {
00102             this.scheduler = Scheduler.connectTo(schedulerURL);
00103             startCommandListener();
00104         } catch (Exception e) {
00105             flush("Cannot create command listener");
00106             System.exit(1);
00107         }
00108     }
00109 
00114     public static void main(String[] args) {
00115         // TODO Auto-generated method stub      
00116         if (args.length == 1) {         
00117                 String schedulerURL = args[0];
00118                 new Communicator(schedulerURL);
00119         }
00120         System.err.println("Usage <java_command> Scheduler_URL");
00121     }
00122 
00132     private String pad(String s, int pad_len) {
00133         if (s.length() >= pad_len) {
00134             return (s);
00135         } else {
00136             int nblanks = pad_len - s.length();
00137             StringBuilder blanks = new StringBuilder(nblanks);
00138 
00139             blanks.setLength(nblanks);
00140             for (int k = 0; k < blanks.length(); ++k)
00141                 blanks.setCharAt(k, ' ');
00142             return (blanks + s);
00143         }
00144     }
00145 
00155     private String center(String s, int pad_len) {
00156         if (s.length() >= pad_len) {
00157             return (s);
00158         } else {
00159             int nblanks = pad_len - s.length();
00160             int half = nblanks / 2;
00161             StringBuilder blanks = new StringBuilder(half);
00162 
00163             blanks.setLength(half);
00164             for (int k = 0; k < blanks.length(); ++k)
00165                 blanks.setCharAt(k, ' ');
00166 
00167             String end = "";
00168             if ((nblanks % 2) == 1) {
00169                 end = " ";
00170             }
00171 
00172             return (blanks + s + blanks + end);
00173         }
00174     }
00175 
00182     private static void log(String msg, boolean isError) {
00183         msg = LOG_HEADER + msg;
00184 
00185         try {
00186             if (isError) {
00187                 logger.error(msg);
00188             } else {
00189                 logger.info(msg);
00190             }
00191         } catch (Exception e) {
00192             /* Log the logging exception ;-) */
00193             System.out.println(e.getMessage() + " when logging : " + msg);
00194         }
00195     }
00196 
00201     public static String getLocalHostName() {
00202         if (hostname == null) {
00203             try {
00204                 hostname = InetAddress.getLocalHost().getCanonicalHostName()
00205                                       .toLowerCase();
00206             } catch (UnknownHostException e) {
00207                 e.printStackTrace();
00208                 hostname = "localhost";
00209             }
00210         }
00211 
00212         return hostname;
00213     }
00214 
00219     private static void configureLogging() {
00220         Appender appender;
00221 
00222         try {
00223             appender = new NTEventLogAppender("ProActiveScheduler");
00224         } catch (java.lang.UnsatisfiedLinkError e) {
00225             String hostname = getLocalHostName();
00226 
00227             Layout layout = new PatternLayout(LOG_PATTERN);
00228             String filename = LOG_DIR + hostname;
00229             RollingFileAppender rfa;
00230 
00231             try {
00232                 new File(LOG_DIR).mkdir();
00233                 rfa = new RollingFileAppender(layout, filename, true);
00234             } catch (IOException ioe) {
00235                 ioe.printStackTrace();
00236 
00237                 return;
00238             }
00239 
00240             rfa.setMaxBackupIndex(0);
00241             rfa.setMaxFileSize(MAX_SIZE);
00242             rfa.setImmediateFlush(false);
00243             writerAppender = rfa;
00244             appender = rfa;
00245         }
00246 
00247         Logger root = Logger.getRootLogger();
00248         root.addAppender(appender);
00249 
00250         /* First message :) */
00251         log("Starting Scheduler command listener", false);
00252     }
00253 
00258     private static void flush(String message) {
00259         if (writerAppender != null) {
00260             writerAppender.setImmediateFlush(true);
00261         }
00262 
00263         log(message, false);
00264 
00265         if (writerAppender != null) {
00266             writerAppender.setImmediateFlush(false);
00267         }
00268     }
00269 
00277     public void helpScreen(String command) {
00278         String result = "";
00279 
00280         if (!command.endsWith(SUB_CMD) && !command.endsWith(STAT_CMD) &&
00281                 !command.endsWith(DEL_CMD) && !command.endsWith(NODES_CMD) &&
00282                 !command.endsWith(KILL_CMD) && !command.endsWith(EXIT_CMD) &&
00283                 !command.equals("?")) {
00284             System.out.println("No such command: " + command.substring(1));
00285             log("No help available for " + command, true);
00286 
00287             return;
00288         }
00289 
00290         result = "\n";
00291 
00292         if (!command.equals("?")) {
00293             String keyword = command.substring(2);
00294 
00295             result += "This command's prototype is: ";
00296 
00297             if (keyword.equals(SUB_CMD)) {
00298                 result += SUB_PROTO;
00299                 result += "\n\n";
00300                 result += "This command is used to submit a job to the scheduler.\n\n";
00301                 result += ("XMLDescriptorOfTheJob is the absolute path to the " +
00302                 "XML Deployment Descriptor of the job to be submitted\n");
00303             } else if (keyword.equals(STAT_CMD)) {
00304                 result += STAT_PROTO;
00305                 result += "\n\n";
00306                 result += ("This command is used to get additionnal information on one " +
00307                 "or all the jobs submitted.\n\n");
00308                 result += ("jobId is the id of the job that we want to know its " +
00309                 "caracteristics. This argument is optional and if not submitted " +
00310                 "this means that we need to get the information on all the jobs\n");
00311             } else if (keyword.equals(DEL_CMD)) {
00312                 result += DEL_PROTO;
00313                 result += "\n\n";
00314                 result += ("This command is used to delete a specific job. " +
00315                 "If the job is already deployed this may cause a brutal interruption " +
00316                 "of the job.\n\n");
00317                 result += "jobId is the id of the job that we want to delete.\n";
00318             } else if (keyword.equals(NODES_CMD)) {
00319                 result += NODES_PROTO;
00320                 result += "\n\n";
00321                 result += ("This command is used to get information of one or all " +
00322                 "the nodes that have been submitted.\n\n");
00323                 result += ("nodeURL is the URL of the node that we need to fetch it's " +
00324                 "characteristics. This argument is optional and if not submitted " +
00325                 "this means that we need to get the information on all the jobs\n");
00326             } else if (keyword.equals(KILL_CMD)) {
00327                 result += KILL_PROTO;
00328                 result += "\n\n";
00329                 result += "This command is used kill the scheduler abruptly.\n";
00330             } else if (keyword.equals(EXIT_CMD)) {
00331                 result += EXIT_PROTO;
00332                 result += "\n\n";
00333                 result += "This command is used to exit this session.\n";
00334             }
00335 
00336             result += "\n";
00337         } else {
00338             result += ("The commands available are: " + SUB_CMD + ", " +
00339             STAT_CMD + ", " + DEL_CMD + ", " + NODES_CMD + ", " + KILL_CMD +
00340             ", " + EXIT_CMD);
00341         }
00342 
00343         result += "\n";
00344         System.out.println(result);
00345     }
00346 
00353     private boolean handleCommand(String command) {
00354         if (command.equals(EXIT_CMD)) {
00355             System.exit(0);
00356         }
00357         if (command.equals("")) {
00358             return true;
00359         }
00360 
00361         if (command.startsWith("?")) {
00362             this.helpScreen(command);
00363             return true;
00364         }
00365 
00366         if (!command.startsWith(SUB_CMD) && !command.startsWith(STAT_CMD) &&
00367                 !command.startsWith(DEL_CMD) && !command.startsWith(NODES_CMD) &&
00368                 !command.startsWith(KILL_CMD)) {
00369             System.out.println("UNKNOWN COMMAND!!...");
00370             log("unknown command submitted: " + command, true);
00371 
00372             return false;
00373         }
00374 
00375         String error = null;
00376 
00377         if (command.startsWith(SUB_CMD)) {
00378             flush(command);
00379 
00380             if (command.equals(SUB_CMD)) {
00381                 error = SUB_PROTO + "\n";
00382             } else {
00383                 //                System.out.println("SUB command invoked ....");
00384                 String XMLDescriptorFile = command.substring(command.indexOf(
00385                             ' ') + 1);
00386                 this.scheduler.fetchJobDescription(XMLDescriptorFile);
00387             }
00388         }
00389 
00390         if (command.startsWith(STAT_CMD)) {
00391             flush(command);
00392 
00393             String jobId = null;
00394             int indexOfWhite = command.indexOf(" ");
00395 
00396             // if index = -1, then the command submitted is "nodes" without parameters
00397             // else we have to extract the node ID
00398             if (indexOfWhite != -1) {
00399                 jobId = command.substring(indexOfWhite + 1);
00400             }
00401 
00402             Vector result = this.scheduler.stat(jobId);
00403             this.viewJobs(result, (jobId != null));
00404 
00405             //            System.out.println("STAT command invoked ....");
00406         }
00407 
00408         if (command.startsWith(DEL_CMD)) {
00409             flush(command);
00410 
00411             if (command.equals(DEL_CMD)) {
00412                 error = DEL_PROTO + "\n";
00413             } else {
00414                 System.out.println("DEL command invoked ....");
00415                 String jobID = command.substring(command.indexOf(' ') + 1);
00416                 this.scheduler.del(jobID);
00417             }
00418 
00419             //            this.scheduler.del(null);
00420         }
00421 
00422         if (command.startsWith(NODES_CMD)) {
00423             flush(command);
00424 
00425             String nodeURL = null;
00426             int indexOfWhite = command.indexOf(" ");
00427 
00428             // if index = -1, then the command submitted is "nodes" without parameters
00429             // else we have to extract the node ID
00430             if (indexOfWhite != -1) {
00431                 nodeURL = command.substring(indexOfWhite + 1);
00432             }
00433 
00434             Vector result = this.scheduler.nodes(nodeURL);
00435             this.viewNodes(result, (nodeURL != null));
00436 
00437             //            System.out.println("NODES command invoked ....");
00438         }
00439 
00440         if (error != null) {
00441             System.out.println("Error using the command. Usage: " + error);
00442             log("Error using the command " +
00443                 error.substring(0, error.indexOf(' ')), true);
00444             return false;
00445         }
00446 
00447         if (KILL_CMD.equals(command)) {
00448             flush(command);
00449             System.exit(0);
00450         }
00451 
00452         return true;
00453     }
00454 
00459     private void startCommandListener() {
00460         InputStreamReader isr = new InputStreamReader(System.in);
00461         BufferedReader reader = new BufferedReader(isr);
00462 
00463         for (;;) {
00464             try {
00465                 System.out.print(" > ");
00466                 String line = reader.readLine();
00467                 handleCommand(line);
00468             } catch (IOException ioe) {
00469                 // ususally there are no error from the keyboard ... 
00470                 ioe.printStackTrace();
00471             }
00472         }
00473     }
00474 
00483     public void viewNodes(Vector nodes, boolean specific) {
00484         Iterator iterator = nodes.iterator();
00485         int nbOfNodes = 0;
00486         int nbOfBusyNodes = 0;
00487         int nbOfReservedNodes = 0;
00488         String result = "";
00489         String header = this.center("Node URL", 45) + this.center("JobId", 74) +
00490             this.pad("status", 14) + "\n" +
00491             "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -" +
00492             " - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \n";
00493 
00494         result += header;
00495 
00496         while (iterator.hasNext()) {
00497             Node node = (Node) iterator.next();
00498 
00499             NodeInformation nodeInformation = node.getNodeInformation();
00500             String jobId = nodeInformation.getJobID();
00501             String nodeURL = nodeInformation.getURL();
00502             String status = "";
00503             nbOfNodes++;
00504 
00505             try {
00506                 if (jobId.equals("-")) {
00507                     status = "free";
00508                 } else {
00509                     int aoNb = node.getNumberOfActiveObjects();
00510                     if (aoNb == 0) {
00511                         status = "reserved";
00512                         nbOfReservedNodes++;
00513                     } else {
00514                         status = "busy";
00515                         nbOfBusyNodes++;
00516                     }
00517                 }
00518             } catch (NodeException e) {
00519                 // TODO Auto-generated catch block
00520                 e.printStackTrace();
00521             }
00522 
00523             result += (this.center(nodeURL, 45) + this.center(jobId, 74) +
00524             this.center(status, 22) + "\n");
00525         }
00526 
00527         String addition = "\nDisplaying all nodes information: ";
00528         if (!specific) {
00529             addition += (nbOfBusyNodes + "/" + nbOfNodes + " busy nodes and " +
00530             nbOfReservedNodes + "/" + nbOfNodes + " reserved nodes");
00531         }
00532         addition += "\n\n";
00533         result = addition + result;
00534 
00535         System.out.println(result);
00536     }
00537 
00546     public void viewJobs(Vector jobs, boolean specific) {
00547         Iterator iterator = jobs.iterator();
00548         String result = "";
00549         String header = this.center("Job ID", 74) +
00550             this.center("submit date", 30) + this.center("estimated time", 18) +
00551             this.center("ressource number", 20) + this.center("status", 10) +
00552             "\n" +
00553             "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -" +
00554             " - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \n";
00555 
00556         result += header;
00557 
00558         while (iterator.hasNext()) {
00559             GenericJob jobDescription = (GenericJob) iterator.next();
00560 
00561             String jobId = jobDescription.getJobID();
00562             Date submitDate = jobDescription.getSubmitDate();
00563             int ressourceNb = jobDescription.getRessourceNb();
00564             int estimatedTime = jobDescription.getEstimatedTime();
00565             String jobStatus = jobDescription.getJobStatus();
00566 
00567             result += (this.center(jobId, 74) +
00568             this.center(String.valueOf(submitDate), 30) +
00569             this.center(String.valueOf(estimatedTime), 18) +
00570             this.center(String.valueOf(ressourceNb), 20) +
00571             this.center(jobStatus, 10) + "\n");
00572         }
00573 
00574         String addition = "\n\n";
00575         result = addition + result;
00576 
00577         System.out.println(result);
00578     }
00579 }

Generated on Mon Jan 22 15:16:11 2007 for ProActive by  doxygen 1.5.1