001    /*
002     * $RCSFile$
003     *
004     * Created on July 12, 2002, 11:29 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.initializer;
024    
025    import gov.bnl.star.offline.scheduler.*;
026    import gov.bnl.star.offline.scheduler.request.Request;
027    import gov.bnl.star.offline.scheduler.request.RequestFactory;
028    
029    import gov.bnl.star.offline.scheduler.util.FilesystemToolkit;
030    import gov.bnl.star.offline.scheduler.util.ConfigToolkit;
031    import gov.bnl.star.offline.scheduler.util.ThreadSafeFilesystemToolkit;
032    
033    
034    import java.io.*;
035    import java.io.File;
036    import java.net.URI;
037    
038    import java.net.URL;
039    import java.util.*;
040    import java.util.ArrayList;
041    
042    import java.util.logging.Level;
043    import org.apache.log4j.Logger;
044    
045    
046    /** Example class to test the scheduler.
047     *
048     * @author Gabriele Carcassi / Levente Hajdu
049     * @version $Revision: 1.23 $ $Date: 2006/11/21 00:41:35 $
050     */
051    public class XMLInitializer implements JobInitializer {
052        static private Logger log = Logger.getLogger(XMLInitializer.class.getName());
053    
054        /** Holds value of property defaultFileListSyntax. */
055        private String defaultFileListSyntax;
056        
057        /** Creates a new instance of SimpleInitializer */
058        public XMLInitializer() { }
059        
060        ThreadSafeFilesystemToolkit threadSafeFilesystemToolkit = new ThreadSafeFilesystemToolkit();
061        
062        private Map prepareDefaults() {
063            Map defaults = new Hashtable();
064            if (defaultFileListSyntax != null)
065                defaults.put("fileListSyntax", defaultFileListSyntax);
066            return defaults;
067        }
068    
069        public Request[] analizeRequest(String xmlFileName) {
070            
071            log.info("Analyzing the request using XMLInitializer: " +
072                xmlFileName);
073            log.info("Parsing the XML file " + xmlFileName);
074            System.out.print("Reading request description file : " + xmlFileName);
075    
076            Request[] requests;
077    
078            try {
079                Map defaults = prepareDefaults();
080                RequestFactory.setDefaults(defaults);
081                Request request = RequestFactory.parseXML(xmlFileName);
082                requests = new Request[] {request};
083            } catch (Exception e) {
084                log.fatal("Parsing failed !", e);
085                System.out.println("There was an error processing the request XML file.");
086                throw new RuntimeException(e.getMessage());
087            }
088    
089    
090            log.debug("Check current scheduling limitations");
091    
092            
093            if(! ConfigToolkit.getToolkit().isFlagSet("SUMS_FLAG_IGNORE_ERRORS")){
094            
095                for (int nRequest = 0; nRequest < requests.length; nRequest++) {
096                    if (!validateRequest(requests[nRequest])) {
097                        throw new RuntimeException("Since the job description wasn't valid, no jobs will be submitted\n" +
098                                "Note: If you believe your job to be valid you can suppress most scheduler errors with the \"-u ie\" option. Example: star-submit -u ie myjob.xml");
099                    }
100                }
101            
102            }
103    
104            return requests;
105        }
106    
107        boolean validateRequest(Request request) {
108            boolean valid = true;
109    
110            // Check whether input file exists
111            //if ((request.getStdIn() != null) && !FilesystemToolkit.checkIfFileExists(request.getStdIn(), false)) {   //replaced for a thread safe version 
112                if ((request.getStdIn() != null) && !threadSafeFilesystemToolkit.threadSafeCheckIfFileExists(request.getStdIn(), false)) {
113                valid = false;
114                log.warn("The file for stdin doesn't exist. Stdin was '" + request.getStdIn() + "'");
115                System.out.println("The file for stdin doesn't exist. Stdin was '" + request.getStdIn() + "'");
116            }
117    
118            // Check whether output and error directory exists
119            //if ((request.getStdOut() != null) && !FilesystemToolkit.checkIfDirExists(request.getStdOut(), false)) {  //replaced for a thread safe version
120            if ((request.getStdOut() != null) && !threadSafeFilesystemToolkit.threadSafeCheckIfDirExists(request.getStdOut(), false)) {  
121                valid = false;
122                log.warn("The directory for stdout doesn't exist. Stdout was '" + request.getStdOut() + "'");
123                System.out.println( "The directory for stdout doesn't exist. Stdout was '" + request.getStdOut() + "'");
124            }
125    
126            //if ((request.getStdErr() != null) && !FilesystemToolkit.checkIfDirExists(request.getStdErr(), false)) {   //replaced for a thread safe version
127            if ((request.getStdErr() != null) && !threadSafeFilesystemToolkit.threadSafeCheckIfDirExists(request.getStdErr(), false)) { 
128                valid = false;
129                log.warn("The directory for stderr doesn't exist. Stderr was '" + request.getStdErr() + "'");
130                System.out.println("The directory for stderr doesn't exist. Stderr was '" + request.getStdErr() + "'");
131            }
132    
133            // Check whether specified input files exist
134            if(checkIfFilesExistLocally){
135                for (int nFile = 0; nFile < request.getInputList().size(); nFile++) {
136                            if ( request.getInputList().get(nFile) instanceof URL) {
137                                
138                                //if (! FilesystemToolkit.checkIfFileExists((URL) request.getInputList().get(nFile), true)){   //replaced because it can hang if the file system goes down
139                                if (! threadSafeFilesystemToolkit.threadSafeCheckIfFileExists((URL) request.getInputList().get(nFile), true)){
140                               
141                                    valid = false;
142                                    System.out.println("Could not find file '"+request.getInputList().get(nFile)+"'");
143                                }
144                            }
145                }
146            }
147            
148    
149            if (!request.getMail() && (request.getStdOut() == null)) {
150                log.warn("The output file wasn't specified and the mail attribute wasn't enabled.");
151                System.out.println("Output file wasn't specified.");
152                System.out.println("You have to add in your xml something like <stdout URL=\"file:/star/u/username/scheduler/out/$JOBID.out\" />");
153                System.out.println("Refer to the documentation on how to specify an output file for your job.");
154                valid = false;
155            }
156            
157            for (int n=0; n < request.getOutputList().size(); n++) {
158                OutputFile out = (OutputFile) request.getOutputList().get(n);
159                boolean validOut = verifyOutput(out);
160                if (valid) valid = validOut;
161            }
162            
163            // Check whether inputOrder was used with local files
164            if (request.getInputOrder() != null) {
165                for (int n=0; (n < request.getInputList().size()) && (valid); n++) {
166                    if (!(request.getInputList().get(n) instanceof CatalogQuery)) {
167                        valid = false;
168                        System.out.println("You can only use the inputOrder option with catalog queries");
169                        log.error("User tried to use the inputOrder option with non catalog queries input");
170                    }
171                }
172            }
173            
174            // Check whether inputs and nProcesses are not declared in the same request
175            if ((request.getNProcesses() != -1) && (request.getInputList().size() != 0)) {
176                valid = false;
177                System.out.println("You cannot set nProcesses for a request that also has inputs");
178                log.error("You cannot set nProcesses for a request that also has inputs");
179            }
180    
181            if (!valid) {
182                log.error("Job request was not valid");
183            }
184    
185            return valid;
186        }
187        
188        static boolean verifyOutput(OutputFile output) {
189            boolean valid = true;
190            if ((output.getToURL() != null) && (output.getActionList().size() != 0)) {
191                System.out.println("You can't mix the toURL attribute for output and the outputActions. Use the <copy> action instead. ");
192                valid = false;
193            }
194            
195            if (output.getToURL() != null) {
196                if (!FilesystemToolkit.checkIfDirExists(output.getToURL(), false)) {
197                    
198                    System.out.println( "The directory for the output doesn't exist. It was '" + output.getToURL() + "'");
199                    
200                }
201            }
202     
203            //TODO rewrite to check output action id's
204    //        List actions = output.getActionList();
205    //        List refs = new ArrayList();
206    //        for (int nAction = 0; nAction<actions.size(); nAction++) {
207    //            OutputAction action = (OutputAction) actions.get(nAction);
208    //            if (action.getFileRef() != null) {
209    //                if (!refs.contains(action.getFileRef())) {
210    //                    if (action.isReferenceGenerator()) {
211    //                        refs.add(action.getFileRef());
212    //                    } else {
213    //                        System.out.println("Output action <" + action.getName() + "> can't be the first action");
214    //                        valid = false;
215    //                    }
216    //                } else {
217    //                    if (action.isReferenceGenerator()) {
218    //                        System.out.println("Output action <" + action.getName() + "> must be the first action");
219    //                        valid = false;
220    //                    } else {
221    //                    }
222    //                }
223    //            }
224    //        }
225            
226            
227    
228                
229            return valid;
230        }
231    
232        /** Getter for property defaultFileListSyntax.
233         * @return Value of property defaultFileListSyntax.
234         *
235         */
236        public String getDefaultFileListSyntax() {
237            return this.defaultFileListSyntax;
238        }
239        
240        /** Setter for property defaultFileListSyntax.
241         * @param defaultFileListSyntax New value of property defaultFileListSyntax.
242         *
243         */
244        public void setDefaultFileListSyntax(String defaultFileListSyntax) {
245            this.defaultFileListSyntax = defaultFileListSyntax;
246        }
247        
248        
249        boolean checkIfFilesExistLocally = true;
250        public void setCheckIfFilesExistLocally(boolean checkIfFilesExistLocally){this.checkIfFilesExistLocally = checkIfFilesExistLocally;}
251        public boolean getCheckIfFilesExistLocally() {return checkIfFilesExistLocally;}
252        
253        
254    }