001    /*
002     * $RCSfile: Scheduler.java,v $ 
003     *
004     * Created on July 12, 2002, 11:04 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;
024    
025    import java.util.*;
026    import java.util.logging.Level;
027    import org.apache.log4j.Logger;
028    import gov.bnl.star.offline.scheduler.util.StatisticsRecorder;
029    import gov.bnl.star.offline.scheduler.util.persistent.ReportWriter;
030    import gov.bnl.star.offline.scheduler.request.Request;
031    
032    /** A scheduler able to verify a job description, chosing the target machine
033     * according to a policy and dispatch the job.
034     * <p>
035     * To create a scheduler, one has to specify a JobInitializer, a Policy and
036     * a Dispatcher. When submitting a request, the job description will be
037     * passed to the JobInitializer which will return an array of JobRequests.
038     * These will be passed one by one to the Policy and then to the Dispatcher.
039     * <p>
040     * By keeping the three function separate from each other, it is possible to
041     * change the underlying queue manager (LSF, Condor, Globus, ... ), policy
042     * or job description specifications.
043     *
044     * @author  Gabriele Carcassi
045     * @version $Revision: 1.26 $ $Date: 2006/11/21 00:41:32 $
046     */
047    public class Scheduler {
048        static private Logger log = Logger.getLogger(Scheduler.class.getName());
049        private JobInitializer initializer;
050        private Policy policy;
051        private Dispatcher dispatcher;
052        private Request[] requests;
053        private List jobs;
054    
055        /** Creates a new scheduler, putting together an initalizer, a policy
056         * and a dispatcher.
057         * @param initializer the part of the scheduler that will create the JobRequests from the xml file
058         * @param policy the part of the scheduler that will decide how and where to execute the jobs
059         * @param dispatcher the part of the scheduler that will dispatch the processes to the underlying
060         * queue
061         */
062        public Scheduler(JobInitializer initializer, Policy policy,
063            Dispatcher dispatcher) {
064            this.initializer = initializer;
065            this.policy = policy;
066            this.dispatcher = dispatcher;
067            log.debug("A new scheduler was created");
068        }
069    
070        /** Creates a new scheduler, putting together an initalizer, a policy
071         * and a dispatcher. In this constructor you specify the class names
072         * instead of the objects. This allows complete real time configuration of
073         * any part of the scheduler.
074         * <p>
075         * Every class specified must have a default constructor.
076         * @param initializerClassName the class name of a class inheriting from JobInitializer
077         * @param policyClassName the class name of a class inheriting from Policy
078         * @param dispatcherClassName the class name of a class inheriting from Dispatcher
079         */
080        public Scheduler(String initializerClassName, String policyClassName,String dispatcherClassName) { 
081            // Load the JobInitializer
082            try {
083                Class initializerClass = Class.forName(initializerClassName);
084                this.initializer = (JobInitializer) initializerClass.newInstance(); 
085            } catch (ClassNotFoundException e) {
086                throw new RuntimeException("Can't find JobInitializer class: " +
087                    initializerClassName);
088            } catch (InstantiationException e) {
089                throw new RuntimeException(
090                    "The default constructor raised an exception: " +
091                    initializerClassName);
092            } catch (IllegalAccessException e) {
093                throw new RuntimeException(
094                    "The default constructor is not public: " +
095                    initializerClassName);
096            } catch (ClassCastException e) {
097                throw new RuntimeException(
098                    "The class provided as a JobInitializer doesn't implement the JobInitializer interface: " +
099                    initializerClassName);
100            }
101    
102            // Load the Policy
103            try {
104                Class policyClass = Class.forName(policyClassName);
105                this.policy = (Policy) policyClass.newInstance();
106            } catch (ClassNotFoundException e) {
107                throw new RuntimeException("Can't find Policy class: " +
108                    policyClassName);
109            } catch (InstantiationException e) {
110                throw new RuntimeException(
111                    "The default constructor raised an exception: " +
112                    policyClassName);
113            } catch (IllegalAccessException e) {
114                throw new RuntimeException(
115                    "The default constructor is not public: " + policyClassName);
116            } catch (ClassCastException e) {
117                throw new RuntimeException(
118                    "The class provided as a Policy doesn't implement the Policy interface: " +
119                    policyClassName);
120            }
121    
122            // Load the Dispatcher
123            try {
124                Class dispatcherClass = Class.forName(dispatcherClassName);
125                this.dispatcher = (Dispatcher) dispatcherClass.newInstance();
126            } catch (ClassNotFoundException e) {
127                throw new RuntimeException("Can't find Dispatcher class: " +
128                    dispatcherClassName);
129            } catch (InstantiationException e) {
130                throw new RuntimeException(
131                    "The default constructor raised an exception: " +
132                    dispatcherClassName);
133            } catch (IllegalAccessException e) {
134                throw new RuntimeException(
135                    "The default constructor is not public: " +
136                    dispatcherClassName);
137            } catch (ClassCastException e) {
138                throw new RuntimeException(
139                    "The class provided as a Dispatcher doesn't implement the Dispatcher interface: " +
140                    dispatcherClassName);
141            }
142        }
143    
144        /** Submits a job through the scheduler. Analizes the xml file, and
145         * dispatches the job according to the policy.
146         * @param xmlFileName the filename of the job description
147         */
148        public void submit(String xmlFileName) {
149            log.info("Scheduling job description contained in: " + xmlFileName);
150            
151            //This line is needed to alow files with the "root:" protcal to be passed
152            //System.setProperty("java.protocol.handler.pkgs", "gov.bnl.star.offline.scheduler.util.protocol" );
153    
154            try {
155                requests = initializer.analizeRequest(xmlFileName);
156            } catch (Exception e) {
157                log.fatal("Job description was invalid", e);
158                throw new RuntimeException(e.getMessage());
159            }
160    
161            for (int nRequest = 0; nRequest < requests.length; nRequest++) {
162                try {
163                    log.debug("String policy.assignTargetMachine(...)");
164                    jobs = policy.assignTargetMachine(requests[nRequest]);
165                } catch (Exception e) {
166                    log.fatal("Policy assignment failed", e);
167                    throw new RuntimeException(e.getMessage());
168                }
169    
170                try {
171                    log.debug("String dispatcher.dispatch(...)");
172                    dispatcher.dispatch(requests[nRequest], jobs);
173    
174                    // write report file 
175                    (new ReportWriter()).writeReport(requests[nRequest]);
176                    
177                    StatisticsRecorder.getInstance().recordStatistics(
178                       requests[nRequest], jobs);
179               
180                } catch (Exception e) {
181                    log.fatal("Job dispatching failed", e);
182                    throw new RuntimeException(e.getMessage());
183                }
184            }
185            log.info("Job dispatched: " + xmlFileName +"\n");
186        }
187    
188        public Request[] getRequests() { return requests; }
189    
190        public List getJobs() { return jobs; }
191    
192    }