001    /*
002     * $RCSfile: Request.java,v $ 
003     *
004     * Created on August 28, 2003, 13:28 AM
005     *
006     * This file is part of the STAR Scheduler.
007     * Copyright (c) 2002-2006 STAR Collaboration - Brookhaven National Laboratory
008     *
009     * STAR Scheduler is free software; you can redistribute it and/or modify
010     * it under the terms of the GNU General Public License as published by
011     * the Free Software Foundation; either version 2 of the License, or
012     * (at your option) any later version.
013     *
014     * STAR Scheduler is distributed in the hope that it will be useful,
015     * but WITHOUT ANY WARRANTY; without even the implied warranty of
016     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
017     * GNU General Public License for more details.
018     *
019     * You should have received a copy of the GNU General Public License
020     * along with STAR Scheduler; if not, write to the Free Software
021     * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
022     */
023    package gov.bnl.star.offline.scheduler.request;
024    
025    import gov.bnl.star.offline.scheduler.*;
026    import gov.bnl.star.offline.scheduler.policy.PassivePolicy;
027    import gov.bnl.star.offline.scheduler.request.rdl.*;
028    import gov.bnl.star.offline.scheduler.util.sandbox.Sandbox;
029    import java.util.*;
030    import java.util.logging.*;
031    
032    import java.net.URL;
033    import org.apache.log4j.Logger;
034    
035    
036    /** Holds all the informations describing a job to be executed by the scheduler.
037     * It contains the machine from which it was dispatched, the command line,
038     * the file required for input and output and the environment variables needed
039     * by the process. It can also handle the information about the processes to be
040     * dispatched in order to execute the job. The scheduler Policy will decide this
041     * information and put it in this class for the Dispatcher to use.
042     *
043     * @author  Gabriele Carcassi & Levente Hajdu & Pavel Jakl
044     * @version $Revision: 1.13 $ $Date: 2006/11/21 00:41:31 $
045     */
046    public class Request implements java.io.Serializable {
047    
048        static private Logger log = Logger.getLogger(Request.class.getName());
049    
050        private Hashtable resources = new Hashtable();
051        private String username;
052        private String authenticatedUser = "";
053        private String name;
054        private String id;
055        private String description;
056        private String requestFileName;
057        private List input = new ArrayList();
058        private List output = new ArrayList();
059        private Sandbox sandbox; 
060        private List jobs = new ArrayList();
061        private List inputOrder;
062        private Application application = null;
063        private Task task = null;
064        private String reportText = " ";
065        private boolean simulation;
066        private boolean mail;
067        /** Holds value of property nProcesses. */
068        private int nProcesses = -1;
069        /** Holds value of property filesPerHour. */
070        private double filesPerHour = Double.POSITIVE_INFINITY;
071        /** Holds value of property fileListType. It can be "paths" or "rootd" or xrootd*/
072        private String fileListType;
073    
074        //private ComponentLibrary componentLibrary;
075        //Map componentLibrary = ComponentLibrary.getInstance().GetLibrary();
076        
077       
078        //private Hashtable comp;
079    
080        public static URL discard;
081    
082        static {
083            try {
084                discard = new URL("file:/dev/null");
085            } catch (Exception e) {
086                // Won't happen
087                discard = null;
088            }
089        }
090    
091        public void setResourceTable(Hashtable resources){
092            this.resources = resources;
093        }
094        
095        public Hashtable getResourceTable(){
096            return resources;
097        }
098                                                                                    
099        /** sets the base ID for the request*/
100        public void setID(String id){
101            this.id = id; 
102        }
103        
104        /** Returns the base jobs ID*/
105        public String getID(){
106            return id; 
107        }
108        
109        /** Sets the list of jobs that where made from this request*/
110        public void setJobs(List jobs){
111            this.jobs = jobs; 
112        }
113        
114        /** Returns a list of all the job objects of this request*/
115        public List getJobs(){
116            return jobs; 
117        }
118        
119        /** Creates a new JobRequest with a title and a description.
120         * Should only be used for legacy JDL request construction.
121         * @param username the username submitting the job
122         * @param command the command line to be executed
123         * @param name a short description of the job
124         * @param description a more detailed description of the job
125         * @param fileName the XML request file name
126         */
127        public Request(String username, String command, String name, String description, String fileName) {
128            this.username = username;
129            this.name = name;
130            this.description = description;
131            this.requestFileName = fileName;
132    
133            task = new ScriptTask();
134            ((ScriptTask)task).setScript(command);
135            
136            //nly used so the componentLibrary gets XML-serializered along with the request
137            //setComponentLibrary(ComponentLibrary.getInstance()); 
138            
139            
140        }
141    
142        /** Creates a new Request and provides XML file name.
143         * @param fileName the XML request file name
144         */
145        public Request(String fileName) {
146            this.requestFileName = fileName;
147        }
148     
149        public Request() {};
150        
151        /** Set to true if this job request is only to be simulated. By simulations we mean
152         * that the scheduler will prepare everything in the same way it would if it was
153         * not a simulation, but it wouldn't execute the final command for the job
154         * submission. For example, it would analize the job, check if it's a valid
155         * request, query the catalog, assign to target, prepare scripts, but don't
156         * dispatch the request.
157         * <p>
158         * This mode is intended to be used by advanced users and developers to check
159         * whether their request was executed correctly. The dispatcher is responsible to
160         * check for this flag, and implement fake dispatching.
161         * @param simulation true if no actual dispatching action is requested
162         */
163        public void setSimulation(boolean simulation) {
164            this.simulation = simulation;
165        }
166    
167        /** Retrieves the filename of the orignal request sent to the scheduler.
168         */
169        public String getRequestFileName() {
170            return requestFileName;
171        }
172        
173        /** Returns the user name under which the job has to run.
174         * @return the username submitting the job
175         */
176        public String getUsername() {
177            return username;
178        }
179    
180        /** Returns true if the job request didn't contain any input.
181         * @return true if not input was specified
182         */
183        public boolean hasNoInput() {
184            return (input.size() == 0);
185        }
186    
187        /** Returns the command line to be executed on the remote machine.
188         * @return the command line to be executed
189         * @deprecated use getTask instead
190         */
191        public String getCommand() {
192            if (task == null || !(task instanceof ScriptTask))
193                return null;
194            return ((ScriptTask)task).getScript();
195        }
196    
197        /** Returns a title describing the job request.
198         * @return a short description of the job
199         */
200        public String getName() {
201            return this.name;
202        }
203        
204        /** Returns a description of the job request.
205         * @return a full description of the job
206         */
207        public String getDescription() {
208            return this.description;
209        }
210    
211        /** Returns the location from which the standard input will be read.
212         * @return the file from which to redirect the standard in
213         * @deprecated use getTask().getStdIn() instead
214         */
215        public URL getStdIn() {
216            if (task == null) return null;
217            return task.getStdIn();
218        }
219    
220        /** Return the location to which the standard output has to be redirected.
221         * @return a file containing the output file where the standard out should be redirected
222         * @deprecated use getTask().getStdOut() instead
223         */
224        public URL getStdOut() {
225            if (task == null) return null;
226            return task.getStdOut();
227        }
228    
229        /** Return the location to which the standard error has to be redirected.
230         * @return a file containing the output file where the standard error should be redirected
231         * @deprecated use getTask().getStdErr() instead
232         */
233        public URL getStdErr() {
234            if (task == null) return null;
235            return task.getStdErr();
236        }
237    
238        /** Return Application value.
239         * @return application
240         */
241        public Application getApplication() {
242            return application;
243        }
244    
245        /** Return Task value.
246         * @return task
247         */
248        public Task getTask() {
249            return task;
250        }
251    
252        /** Returns the list of data files that were requested as an input of the
253         * job.
254         * @return the requested input file list
255         */
256        public List getInputList() {
257            return input;
258        }
259    
260        /** Return the list of data files that were requested as an output of the
261         * job.
262         * @return the requested output file list
263         */
264        public List getOutputList() {
265            return output;
266        }
267        
268         public void setOutputList(List output) { 
269             this.output = output;
270         }    
271        
272    
273        /** Returns true if this job requests is only a simulations. By simulations we mean
274         * that the scheduler will prepare everything in the same way it would if it was
275         * not a simulation, but it wouldn't execute the final command for the job
276         * submission. For example, it would analize the job, check if it's a valid
277         * request, query the catalog, assign to target, prepare scripts, but don't
278         * dispatch the request.
279         * <p>
280         * This mode is intended to be used by advanced users and developers to check
281         * whether their request was executed correctly. The dispatcher is responsible to
282         * check for this flag, and implement fake dispatching.
283         * @return true if the scheduler shouldn't dispatch the job
284         */
285        public boolean getSimulation() {
286            return simulation;
287        }
288    
289        /** Returns true if communication by mail from the queuing system is allowed.
290         * @return true if the output, or other messages, can be sent by mail
291         */
292        public boolean getMail() {
293            return mail;
294        }
295    
296        /** Getter for property fileListType.
297         * @return Value of property fileListType.
298         *
299         */
300        public String getFileListType() {
301            if (fileListType==null || fileListType==""){
302                this.fileListType="paths";
303            }
304            return this.fileListType;
305        }
306        
307        /** Getter for property filesPerHour.
308         * @return Value of property filesPerHour.
309         *
310         */
311        public double getFilesPerHour() {
312            return this.filesPerHour;
313        }
314        
315        /** Getter for property inputOrder.
316         * @return Value of property inputOrder.
317         *
318         */
319        public List getInputOrder() {
320            return this.inputOrder;
321        }
322    
323        /** Add a Resource value to this Request
324         * @param resource to add
325         *
326         */
327        public void addResource(Resource resource) {
328            resources.put(resource.getName(), resource);
329        }
330    
331        /** Get a Resource value from this Request
332         * If the Resource doesn't exist, return a default Resource
333         * @param name of resource to get
334         *
335         */
336        public Resource getResource(String name) {
337            Resource resource = (Resource)resources.get(name);
338            if (resource != null)
339                return resource;
340            else
341                return new Resource("default");
342        }
343    
344        /** Set a Resource's min value
345         * If the Resource doesn't exist, create it
346         * @param name of Resource
347         * @param min value
348         *
349         */
350        public void setResourceMin(String name, int min) {
351            Resource resource = (Resource)resources.get(name);
352            if (resource == null)
353                resource = new Resource(name);
354            resource.setMin(min);
355            resources.put(name, resource);
356        }
357    
358        /** Set a Resource's max value
359         * If the Resource doesn't exist, create it
360         * @param name of Resource
361         * @param max value
362         *
363         */
364        public void setResourceMax(String name, int max) {
365            Resource resource = (Resource)resources.get(name);
366            if (resource == null)
367                resource = new Resource(name);
368            resource.setMax(max);
369            resources.put(name, resource);
370        }
371    
372        /** Getter for property nProcesses. Returns -1 if nProcess is not set.
373         * @return Value of property nProcesses.
374         *
375         */
376        public int getNProcesses() {
377            return this.nProcesses;
378        }
379        
380        /** Setter for property nProcesses.
381         * @param nProcesses New value of property nProcesses.
382         *
383         */
384        public void setNProcesses(int nProcesses) {
385            if (nProcesses <= 0) 
386                throw new IllegalArgumentException(
387                    "nProcesses must be greater than zero");
388            this.nProcesses = nProcesses;
389        }
390        
391        public void addToReportText(String Text) { 
392            reportText = reportText.concat(Text).concat("\n"); 
393        }
394    
395        public void SetReportText(String Text){
396            this.reportText = Text;
397        }
398    
399        public String GetReportText() { return reportText; }
400     
401       /** Set the request name
402        * @param name
403        */
404        
405    //    protected void setName(String name) {     LBH
406        public void setName(String name) {
407            this.name = name;
408        }
409    
410        /** Sets the command line to be executed to the remote machine. 
411         * Should only be called for JDL request, in which case task
412         * was created in the constructor
413         * @param command the command line to be executed
414         * @deprecated use setTask instead
415         */
416        public void setCommand(String command) {
417            if (task instanceof ScriptTask) 
418                ((ScriptTask)task).setScript(command);
419        }
420    
421        /** Sets the location from which the standard input will be reed.
422         * @param stdin a file containing the input file to be redirected in the standard in
423         * @deprecated use setTask() instead
424         */
425        
426            public void setStdIn(URL stdin) {
427    //    protected void setStdIn(URL stdin) {    LBH
428            if (task != null) 
429                task.setStdIn( stdin );
430        }
431    
432        /** Sets the location in which the standard output will be saved.
433         * @param stdout a file containing the output file where the standard out should be redirected
434         * @deprecated use setTask() instead
435         */
436    //    protected void setStdOut(URL stdout) {
437         public void setStdOut(URL stdout) {   
438            if (task != null) 
439                task.setStdOut( stdout );
440        }
441                                                                                    
442        /** Sets the location in which the standard error will be saved.
443         * @param stderr a file containing the output file where the standard error should be redirected
444         * @deprecated use setTask() instead
445         */
446        //protected void setStdErr(URL stderr) {    LBH
447           public void setStdErr(URL stderr) {
448            if (task != null) 
449                task.setStdErr( stderr );
450        }
451    
452        /** Set Application attribute.
453         * @param app
454         */
455           public void setApplication(Application app) {
456     //   protected void setApplication(Application app) {
457            this.application = app;
458        }
459    
460        /** Set Task attribute.
461         * @param task
462         */
463           public void setTask(Task task) {
464    //    protected void setTask(Task task) {
465            this.task = task;
466        }
467    
468        /** Specifies if the queuing system is allowed to send mail to the user.
469         * @param mail true if the user is allowed to recieve mail
470         */
471     public  void setMail(boolean mail) {
472     //   protected void setMail(boolean mail) {
473            this.mail = mail;
474        }
475                                                                                    
476        /** Setter for property fileListType.
477         * @param fileListType New value of property fileListType.
478         *
479         */
480          public void setFileListType(String fileListType) {
481     //   protected void setFileListType(String fileListType) {
482            if (!"rootd".equals(fileListType) && !"paths".equals(fileListType) && !"xrootd".equals(fileListType) ) {
483                throw new RuntimeException(
484                    "fileListType can only be '[x]rootd' or 'paths'");
485            }
486            if ("rootd".equals(fileListType) && !PassivePolicy.isRootdAvailable()){
487                throw new RuntimeException(
488                    "You are using 'rootd' syntax but 'rootd' is not available at the current queue !!"
489                );
490            }
491            //check if they specify xrootd syntax and xrootd is available ?
492            if ("xrootd".equals(fileListType) && !PassivePolicy.isXrootdAvailable()){
493                throw new RuntimeException(
494                    "You are using 'xrootd' syntax but 'xrootd' is not available at the current queue !!"
495                );
496            }
497            this.fileListType=fileListType;
498        }
499    
500    
501        /** Setter for property filesPerHour.
502         * @param filesPerHour New value of property filesPerHour.
503         *
504         */
505       public void setFilesPerHour(double filesPerHour) {
506       // protected void setFilesPerHour(double filesPerHour) {
507            this.filesPerHour = filesPerHour;
508        }
509    
510        /** Setter for property inputOrder.
511         * @param inputOrder New value of property inputOrder.
512         *
513         */
514       public  void setInputOrder(List inputOrder) {
515    //    protected void setInputOrder(List inputOrder) {
516            this.inputOrder = inputOrder;
517        }
518    
519       public  void prepareInputOrder(String commaSeparated) {
520    //   protected void prepareInputOrder(String commaSeparated) {
521            inputOrder = new ArrayList();
522            StringTokenizer t = new StringTokenizer(commaSeparated, ",");
523            while (t.hasMoreTokens()) {
524                inputOrder.add(t.nextToken());
525            }
526        }
527       
528       
529       
530       
531       public String getAuthenticatedUser(){return authenticatedUser;}
532       public void setAuthenticatedUser(String authenticatedUser){this.authenticatedUser = authenticatedUser;}
533       
534    
535    
536        public void setSandbox(Sandbox sandbox){this.sandbox = sandbox;}
537        public Sandbox getSandbox(){return sandbox;}
538       
539    
540       /**Only used so the componentLibrary gets XML-serializered along with the request*/
541       /*
542       public List getComponentLibrary(){
543           //return componentLibrary;
544    
545           List Library = new ArrayList();
546           List LibraryKey = new ArrayList();
547           List LibraryObject = new ArrayList();
548           
549           Library.add(LibraryKey);
550           Library.add(LibraryObject);
551                
552           for (Enumeration e = ((Hashtable) ComponentLibrary.getInstance().GetLibrary()).keys() ; e.hasMoreElements() ;) {
553             //System.out.println(e.nextElement());
554               Object key  = e.nextElement();
555               Object obj = ((Hashtable) ComponentLibrary.getInstance().GetLibrary()).get(key);
556               LibraryKey.add(key);
557               LibraryObject.add(obj);
558               
559               System.out.println(">>>>>>>>>>" + ((String)key));
560           }
561      
562           //((Hashtable) ComponentLibrary.getInstance().GetLibrary()).values();
563           //return (Hashtable) ComponentLibrary.getInstance().GetLibrary().
564           return Library;
565       }
566       */
567       /**Only used so the componentLibrary gets XML-serializered along with the request*/
568       /*
569       public void setComponentLibrary(List componentLibrary){
570           //this.componentLibrary = componentLibrary;
571           //
572           Hashtable Lib = new Hashtable();
573           
574           
575           List keys = (List) componentLibrary.get(0);
576           List obj = (List) componentLibrary.get(1);
577           
578           for(int i = 0; i != keys.size(); i++){
579               Lib.put( keys.get(i)   , obj.get(i)  );  
580           }
581           
582           ComponentLibrary.getInstance().SetLibrary(Lib);
583           
584           
585       }
586       */
587    
588    }