001    /*
002     * StandardExpressionResourceStrategy.java
003     *
004     * This file is part of the STAR Scheduler.
005     * Copyright (c) 2002-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    
022    package gov.bnl.star.offline.scheduler.Dispatchers;
023    
024    import gov.bnl.star.offline.scheduler.Job;
025    import gov.bnl.star.offline.scheduler.catalog.PhysicalFile;
026    import gov.bnl.star.offline.scheduler.Dispatchers.AbstractResourceStrategy;
027    
028    
029    import java.net.URL;
030    import java.lang.Math;
031    import java.util.List;
032    import java.lang.Integer;
033    import java.util.ArrayList;
034    import java.util.Hashtable;
035    import java.util.Enumeration;
036    import java.util.logging.Level;
037    import org.apache.log4j.Logger;
038    
039    
040    
041    /**
042     * Used to build resource requirement strings defined by regular  expressions  to be used in dispatch commands.
043     *
044     * @author  Levente Hajdu
045     */
046    public class RegXResourceStrategy implements AbstractResourceStrategy, java.io.Serializable{
047        
048        /** Creates a new instance of StandardExpressionResourceStrategy */
049        public RegXResourceStrategy() {}
050        
051        static private Logger log = Logger.getLogger(RegXResourceStrategy.class.getName());
052        
053        private int base = 0;
054        private int fileFactor = 1;
055        private int max = Integer.MAX_VALUE;
056        private Hashtable UsedResources = new Hashtable();
057        private String delimiterCharacter =",";
058        
059        private String regXResourceNameSelection = "(.{5})(.*)";
060        private String regXResourceNameReplacement = "$1={value}"; 
061        
062        private List mustMatchList = new ArrayList();
063        private List mustNotMatchList = new ArrayList();
064        
065        /**Retunes the parameter base in the formula resourcesConsumed=base+(fileFactor*nItemsMatched)  which is used to calculate the resources consumed. */
066        public int getBase() { return base; }
067        /**Sets the parameter base in the formula resourcesConsumed=base+(fileFactor*nItemsMatched)  which is used to calculate the resources consumed. */
068        public void setBase(int base) { this.base = base; }
069        
070        /**Retunes the parameter fileFactor in the formula resourcesConsumed=base+(fileFactor*nItemsMatched)  which is used to calculate the resources consumed. */
071        public int getFileFactor() { return fileFactor; }
072        /**Sets the parameter fileFactor in the formula resourcesConsumed=base+(fileFactor*nItemsMatched)  which is used to calculate the resources consumed. */
073        public void setFileFactor(int fileFactor) { this.fileFactor = fileFactor; }
074        
075        /** Sets returns the max value that a resource can consume.
076         *  If the resources consumed pass this limit, the number returned will be the limmit.*/
077        public int getMax() { return max; }
078        /** returns the max value that a resource can consume.
079         *  If the resources consumed pass this limit, the number returned will be the limmit.*/
080        public void setMax(int max) { this.max = max; }
081        
082        /**Retunes the amount of resources consumed according to the calculation resourcesConsumed=base+(fileFactor*nItemsMatched);  
083         * This is however limited by the value of "max". */
084        public String calcUsage(int unitsUsed){ return String.valueOf(Math.min(getMax(), getBase() + (fileFactor * unitsUsed))); }
085        
086        
087        public String getRegXResourceNameSelection(){ return regXResourceNameSelection; }
088        public void setRegXResourceNameSelection(String regXResourceNameSelection){this.regXResourceNameSelection = regXResourceNameSelection;} 
089        
090        public String getRegXResourceNameReplacement(){ return regXResourceNameReplacement; }
091        public void setRegXResourceNameReplacement(String regXResourceNameReplacement){this.regXResourceNameReplacement = regXResourceNameReplacement; }
092        
093        /**Returns the character that is used as the delimiter, this is most usaly the "," and this is the default if not set.*/
094        public String getDelimiterCharacter(){return delimiterCharacter;}
095        /**Sets the character that is used as the delimiter, this is most usaly the "," and this is the default if not set.*/
096        public void setDelimiterCharacter(String delimiterCharacter){this.delimiterCharacter = delimiterCharacter;} 
097        
098        public void addResourceMustMatch(String mustMatch){this.mustMatchList.add(mustMatch);}
099        public List getMustMatchList(){ return mustMatchList;}
100        public void setMustMatchList(List mustMatchList){this.mustMatchList = mustMatchList;}
101        
102        public void addResourceMustNotMatch(String mustNotMatch){this.mustNotMatchList.add(mustNotMatch);}
103        public List getMustNotMatchList(){ return mustNotMatchList;}
104        public void setMustNotMatchList(List mustNotMatchList){this.mustNotMatchList = mustNotMatchList;}
105        
106        
107        
108        /** This function returns a string that represents the resource usage of the job, in such a format that it can be passed to the batch system. 
109         * @param job The job from which the resource usage string will be generated.
110         */
111        public String prepareResourceUsageSwitch(gov.bnl.star.offline.scheduler.Job job) {
112    
113            
114            log.debug("biulding resource usage switch for job " + job.getJobID() );
115            try{    
116            
117                UsedResources.clear(); //clear the resource table
118          
119                for (int i = 0; i < job.getInput().size(); i++) {  //loop over all the files in job 
120                    PhysicalFile file = (PhysicalFile) job.getInput().get(i);
121                    if ("NFS".equals(file.getStorage())) {
122    
123                        String path = file.getPath();
124    
125                        boolean hasMatche = true; 
126    
127                        for(int j = 0; j != mustMatchList.size(); j++) //must match evering on the mustmatchlist or else hasMatched is false
128                            if(! (path.matches(  ((String) mustMatchList.get(j))))) hasMatche = false;
129    
130                        for(int j = 0; j != mustNotMatchList.size(); j++) //must not match anything on the mustNotmatchlist or else hasMatched is false
131                            if(path.matches( (String) mustNotMatchList.get(j))) hasMatche = false; 
132    
133    
134                        if(hasMatche){
135                              String resName = path.replaceAll(regXResourceNameSelection, regXResourceNameReplacement);
136                           // String resName = path.replaceAll("(^.*/data0||^.*/data)(\\d+)(.*)", "SD$2={value}");
137    
138                            if(UsedResources.containsKey(resName)){ //is this resource already on the list
139                                int units = ((Integer) UsedResources.get(resName)).intValue() + 1 ;
140                                UsedResources.remove(resName);
141                                UsedResources.put(resName, Integer.valueOf(String.valueOf(units)));
142                            }
143                            else UsedResources.put(resName, Integer.valueOf("1") );  //If the iteam is not already on the list make a new entry
144                        }
145                    }    
146                }
147    
148               if(UsedResources.isEmpty()) return null; //If nothing is used return null 
149    
150               String resourcesString = ""; //The string that will hold the final value
151    
152               for (Enumeration e = UsedResources.keys() ; e.hasMoreElements() ;) {  //Collect all the values from the hashtable and concatenate then in to one delaminated string.  
153                   String ResKey = (String) e.nextElement();
154                   resourcesString = resourcesString.concat(ResKey.replaceAll("\\Q{value}\\E", calcUsage(((Integer) UsedResources.get(ResKey)).intValue())) + delimiterCharacter);  //replace the "{value}" string with the true value  
155               }
156    
157               return resourcesString.replaceAll("(.)(\\Q" + delimiterCharacter + "\\E$)","$1");  //Remove the last "," and return the value
158               
159            }catch(Exception ex){ 
160                String warning = "An error occurred while trying to build a resource(s) string. If uncorrected this could lead to farm or resource instability.\n" + ex;
161                System.out.println(warning);
162                log.warn(warning);
163                return null;
164            }       
165        } 
166    }
167       
168        
169        
170        
171    
172