001    /*
002     * CommandLineReDispatch.java
003     *
004     * This file is part of the STAR Scheduler.
005     * Copyright (c) 2003-2006 STAR Collaboration - Brookhaven National Laboratory
006     *
007     * STAR Scheduler is free software; you can redistribute it and/or modify
008     * it under the terms of the GNU General Public License as published by
009     * the Free Software Foundation; either version 2 of the License, or
010     * (at your option) any later version.
011     *
012     * STAR Scheduler is distributed in the hope that it will be useful,
013     * but WITHOUT ANY WARRANTY; without even the implied warranty of
014     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
015     * GNU General Public License for more details.
016     *
017     * You should have received a copy of the GNU General Public License
018     * along with STAR Scheduler; if not, write to the Free Software
019     * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
020     */
021    package gov.bnl.star.offline.scheduler.util.persistent;
022    
023    import gov.bnl.star.offline.scheduler.util.persistent.SessionReader;
024    import gov.bnl.star.offline.scheduler.Job;
025    import gov.bnl.star.offline.scheduler.request.Request;
026    import gov.bnl.star.offline.scheduler.GenericCompositeDispatcher;
027    import gov.bnl.star.offline.scheduler.ComponentLibrary;
028    import gov.bnl.star.offline.scheduler.SchedulerCommandLine;
029    import gov.bnl.star.offline.scheduler.LogFormatter;
030    import java.util.List;
031    import java.util.ArrayList;
032    import java.lang.Character;
033    
034    //trying to fix logging problem 
035    import java.util.Map;
036    import java.util.logging.FileHandler;
037    import java.util.logging.Handler;
038    import java.util.logging.Level;
039    import org.apache.log4j.Logger;
040    import java.util.Date; 
041    
042    /**
043     * The main class for resubmitting already dispatched jobs.
044     * note: This main is called from the star-submit if (and only if) the users options are (-kr,-k,-r,-s,-n,-f, -h)
045     * @author  Levente Hajdu
046     */ 
047    public class CommandLineReDispatch {
048        
049        public Request request;
050        
051        
052        /** Creates a new instance of CommandLineReDispatch */
053        public CommandLineReDispatch() {
054            System.out.println(Usage());
055        }
056        
057    
058        
059        static List jobs = new ArrayList();
060        static List jobsToResub = new ArrayList();
061        
062        /**
063         * @param args the command line arguments for resubmitting
064         */
065        public static void main(String[] args) {
066            
067            boolean Kill = false;
068            boolean Resub = false;
069            boolean Stat = false;
070            boolean Faild = false;
071            boolean NoID = false;
072            //boolean PrintUsage = false;
073            
074            
075    
076             for (int i = 0; i < args.length; i++) {
077                if(args[i] .startsWith("-h")){
078                   System.out.println(Usage());
079                   return; 
080                }   
081             }
082            
083            if((args.length < 3)){
084                System.out.println("missing arguments\nTry `star-submit -h' for more information.");
085                return;
086            }
087            
088            if((args.length != 5)){
089                System.out.println("You must have exactly 3 arguments. ");
090                return;
091            }
092            
093            String configFile = args[0]; //the config file name
094            String site = args[1]; 
095            String option  = args[2]; //The option the user picked ex: -k,-r,-s,-f,-kr 
096            String range = args[3]; //The jobs selected  ex: 1,2,3 or 1-3 or "all"
097            String fileName = args[4]; //The xml file the jobs came from
098    
099            if(option .startsWith("-kr")){ //used to kill selected jobs and then resubmit the same selected jobs
100                Kill = true;
101                Resub = true; 
102            }
103            else if(option .startsWith("-k")){ //used to kill selected jobs 
104                Kill = true;
105            }
106            else if(option .startsWith("-r")){ //used to submit selected jobs
107                Resub = true;
108            }
109            else if(option .startsWith("-s")){ //used to get the status of selected jobs
110                Stat = true;
111            }
112            else if(option .startsWith("-n")){ //used to submit selected job that don't have at lest one job ID
113                NoID = true;
114            }
115            else if(option .startsWith("-f")){ //used to submit selected job that don't have at lest one job ID
116                Faild = true;
117            }
118            else{
119                System.out.println("The option \"" + option + "\"is not valid. The valid options are -kr, -k, -r, -s, -i, -f"); 
120                System.out.println(Usage());
121                return;
122            }
123            
124            //ComponentLibrary must be ready before SessionReader is called
125            ComponentLibrary.initLibrary(configFile); //In case of STAR BNL this value would be [configFile="/afs/rhic/star/users/starjobs/dev/rcfConfig.xml";]
126            ComponentLibrary.getInstance().addComponent("localSite", site);
127            
128            SessionReader session = new SessionReader(fileName); //try to open the file
129            
130            if(! session.isOpen()){ //if the arg. pass as the file name did not open the file, test to see if the user only submitted the session id and fill in the full file name and try opeeing again
131                if(fileName.matches(".*[0123456789ABCDEF]*") && (! fileName.matches(".*\\.session\\.xml")) ){
132                    String modFileName = fileName + ".session.xml";
133                    System.out.println("Trying again with :" + modFileName);
134                    session = new SessionReader(modFileName);
135                }
136            }
137                
138            if(! session.isOpen()){    
139                System.out.println("The file name may be wrong, or the file may be bad.");
140                return; //no error message is printed becuase the error is witten out by the session reader 
141            }
142            else{
143               System.out.println("Session file is open."); 
144            }
145            
146            jobs = session.getJobs(); //get all the jobs out of the object
147            
148            if(range.toLowerCase().startsWith("all")) jobsToResub = jobs;
149            else{
150                
151                //test to see of the Range the user submited is in the format of a range or a value
152                boolean isRange = false;
153                boolean isValues = false;
154                for(int i = 0; i != range.length(); i++){ //read the range value one char at a time
155                    if(Character.isDigit(range.charAt(i))); //get the next one
156                    else if(range.charAt(i) == '-') isRange = true;
157                    else if(range.charAt(i) == ',') isValues = true;
158                    else{
159                        System.out.println("The character \"" + range.charAt(i) + "\" in the range element \"" + range + "\" is note valide.");
160                        return;
161                    } 
162                }
163                
164                //test for errors
165                if(isRange && isValues){
166                    System.out.println("The value \"" +  range + "\" can not be both a range and a set.\nYou an not use both \",\" and \"-\""); 
167                    return;
168                }
169                
170                //if the value is a range
171                int i = 0;
172                if(isRange){
173                    String ValOne =""; //value one
174                    for(; range.charAt(i) != '-'; i++) ValOne = ValOne.concat(String.valueOf(range.charAt(i))); //get the first vlaue into the string ValOne
175                    i++;   
176                    String ValTwo =""; //value one
177                    for(; i != range.length(); i++) ValTwo = ValTwo.concat(String.valueOf(range.charAt(i))); //get the next vlaue into the string ValTwo
178               
179                    int upperValue = 0;
180                    int lowerValue = 0;
181                    
182                    try{ //cast the strings values in to int
183                        lowerValue = Integer.parseInt(ValOne);
184                        upperValue = Integer.parseInt(ValTwo);
185                    }
186                    catch (Exception e){
187                        System.out.println("Could not parse the range values"); 
188                        return;
189                    }
190                    
191                    if(lowerValue > upperValue){ //sort the uper and lower values
192                        int buff = lowerValue;
193                        lowerValue = upperValue;
194                        upperValue = buff;
195                    }
196                    
197                    for(;(upperValue + 1) != lowerValue; lowerValue++){
198                        int resubListSize = jobsToResub.size();
199                        for(int j = 0; j != jobs.size(); j++){
200                            Job job = (Job)jobs.get(j);
201                            if( job.getJobID().endsWith("_" + String.valueOf(lowerValue))){ //find the job id that end with the same number as the lower limit
202                                jobsToResub.add(job);
203                            } 
204                        }
205                        if(resubListSize == jobsToResub.size()){
206                            System.out.println("Could not find job number : " + lowerValue);
207                        }  
208                    }   
209                }
210                
211                
212                else if(isValues){ //if the user entered the range as a set of values
213                   String Value = "";
214                   while(!(i >= range.length())){
215                        Value = "";
216                        for(;(range.charAt(i) != ',') && !((i+1) >= range.length()); i++) Value = Value.concat(String.valueOf(range.charAt(i)));
217                        if((i+1) >= range.length()) Value = Value.concat(String.valueOf(range.charAt(i)));
218                        i++;
219                        
220                        int resubListSize = jobsToResub.size();
221                        for(int j = 0; j != jobs.size(); j++){
222                            Job job = (Job)jobs.get(j);
223                            if( job.getJobID().endsWith("_" + Value)){ //find the job id that end with the same number as the lower limit
224                                jobsToResub.add(job);
225                            } 
226                        }
227                        if(resubListSize == jobsToResub.size()){
228                            System.out.println("Could not find job number : " + Value);
229                        }
230                       
231                    }
232                }
233                else{ //if the user just entered one nuber
234                    try{ Integer.parseInt(range);}
235                    catch (Exception e){
236                        System.out.println("Could not parse the range values"); 
237                        return;
238                    }
239                    
240                    int resubListSize = jobsToResub.size();
241                    for(int j = 0; j != jobs.size(); j++){
242                        Job job = (Job)jobs.get(j);
243                        if( job.getJobID().endsWith("_" + range)){ //find the job id that end with the same number as the lower limit
244                            jobsToResub.add(job);
245                        } 
246                    }   
247                    if(resubListSize == jobsToResub.size()){
248                        System.out.println("Could not find job number : " + range);
249                    }           
250               } 
251          
252             }   
253            
254            //if some jobs there found
255            if(jobsToResub.size() != 0){
256                //For the scheduler to run the ComponentLibrary and log file must be stared up.
257                
258    
259                
260    //            Handler[] handlers = Logger.getLogger("").getHandlers();
261    //            for (int index = 0; index < handlers.length; index++) {
262    //                handlers[index].setFormatter(new LogFormatter());
263    //                handlers[index].setLevel(Level.OFF);
264    //            }
265    //            Logger.getLogger("").setLevel(Level.OFF);
266                SchedulerCommandLine CommandLine = new SchedulerCommandLine();
267                CommandLine.setFileLogging();
268                
269                //make new dispatcher
270                GenericCompositeDispatcher dispatcher = new GenericCompositeDispatcher();
271               
272                if(Kill) dispatcher.Kill(session.getRequest(), jobsToResub); //Kill all jobs in the jobsToResub list 
273                
274                if(NoID){ //resubmit all jobs that do not have a job id
275                    List faildJobsToResub = new ArrayList();
276                    for(int j = 0; j != jobsToResub.size(); j++){
277                        Job job = (Job) jobsToResub.get(j);
278                        if(job.getProcesseIDs().size() == 0)faildJobsToResub.add(job);
279                    }
280                    dispatcher.dispatch(session.getRequest(), faildJobsToResub);    
281                }
282                
283                if(Faild){//resubmit all the jobs that failed to be dispached
284                    List faildJobsToResub = new ArrayList();
285                    for(int j = 0; j != jobsToResub.size(); j++){
286                        Job job = (Job) jobsToResub.get(j);
287                        if(!job.getDispatchSuccessful())faildJobsToResub.add(job);
288                    }
289                    dispatcher.dispatch(session.getRequest(), faildJobsToResub);
290                
291                }
292                
293                if(Resub){ //resubmit all jobs
294                //Send all the jobs on the jobsToResub to the GenericCompositeDispatcher
295                dispatcher.dispatch(session.getRequest(), jobsToResub);
296                }
297                
298                if(Stat){ //print the status of each job
299                    for(int j = 0; j != jobsToResub.size(); j++){
300                        Job job = (Job) jobsToResub.get(j);
301                        for(int k = 0; k != job.getProcesseIDs().size(); k++){
302                            System.out.println(dispatcher.Status(job, k));
303                        }   
304                    } 
305                }
306            }
307            else{ //if there where no jobs in the uses request, let the user know
308                System.out.println("(No jobs found)");
309            }
310    
311    }
312        
313        public static String Usage(){
314            return "Usage :\n\n" +
315            "  star-submit -[OPTION] [JDLFile.xml]                //This syntax is used to submit a job (the options are not required )" +
316            "\n\n"+
317            "  [OPTIONS]:\n"+
318            "    -policy [policy name from config file]           //Selects a policy, if not used the default policy will be selected.\n"+
319            "    -dispatcher [dispatcher name from config file]   //This option is deprecated (but still available).\n"+
320            "\n\n"+
321            "  Example:\n" +
322            "    star-submit MyJobDescription.xml" +
323            "\n\n\n\n"+
324            "Alternative usage  :\n\n" +
325            "  star-submit -[OPTION] [JobSelection] [SessionFile.xml]  //This syntax is used after submission (the options are required )\n" +      
326            "                                                          //Note: Any changes made to your .csh files will be over written.\n\n" +
327            "  [OPTIONS]:\n"+
328            "    -r                    //resubmit selected job(s)\n" +
329            "    -k                    //kill selected job(s)\n" +
330            "    -kr                   //kill and resubmit selected job(s)\n"+
331            "    -s                    //get the status of selected job(s)\n"+
332            "    -n                    //submits selected job(s) that have no job ID (jobs that have been killed or failed to dispatch)\n"+
333            "    -f                    //resubmits all selected job(s) that failed to dispatch\n"+
334            "    -h                    //help"+
335            "\n\n"+
336            "  [JobSelection]:\n"+
337            "    n                     //any singal job number\n"+
338            "    a-z                   //jobs abcdefghijklmnopqrstuvwxyz\n"+
339            "    a,q,c,h               //only jobs a, q, c, and h\n"+
340            "\n\n"+
341            "  Examples:\n" +
342            "    star-submit -kr all DD9CFB586F4139E8D14C6.session.xml        //Kill and resubmit all jobs:\n" +
343            "    star-submit -r 1,2,3,5 DDD9CFB586F4139E8D14C6.session.xml    //Resubmit jobs 1,2,3, and 5\n" +
344            "    star-submit -s 5 DD9CFB586F4139E8D14C6.session.xml           //Get the status of job 5\n";
345        }
346    }