001 /* 002 * Queue.java 003 * 004 * Created on July 2, 2004, 7:37 PM 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 024 package gov.bnl.star.offline.scheduler; 025 026 import gov.bnl.star.offline.scheduler.BatchSystem; 027 import gov.bnl.star.offline.scheduler.Dispatchers.QueueDiscriptorBase; 028 import gov.bnl.star.offline.scheduler.request.Request; 029 import gov.bnl.star.offline.scheduler.util.RDLApplicationResolver; 030 import gov.bnl.star.offline.scheduler.util.ConfigToolkit; 031 import gov.bnl.star.offline.scheduler.AccessMethod; 032 import gov.bnl.star.offline.scheduler.LocalAccessPoint; 033 034 import java.util.ArrayList; 035 036 import java.util.List; 037 038 /** Description of a batch system queue. 039 * @author Levente Hajdu 040 */ 041 public class Queue { 042 043 /** Creates a new instance of Queue */ 044 public Queue() {} 045 046 private String Site; 047 private String QueueName ="No Name"; 048 private String Cluster; 049 private int TimeLimit = -1; //the max time limit in min a jobs can run for inside this queue 050 private int maxMemory = -1; //The max ram a job a use before it is killed, if it runs in this queue 051 private int maxFiles = -1; 052 private int searchOrderPriority = 1; 053 private boolean Local = false; 054 private String ID = "No ID"; 055 private String Type ="?"; 056 private String Messages = "No Message"; 057 // private Dispatcher dispatcher; // The dispatcher associated with this queue when submitting localy. 058 // private Dispatcher gridDispatcher; //The dispatcher associated with this queue when submitting between sites. 059 060 private BatchSystem batchSystem; 061 062 063 List accessMethods = new ArrayList(); 064 /**Return the list of all access methods under which this is queue is listed in the config **/ 065 public List getAccessMethods(){ return accessMethods; } 066 /**Resets the accessMethods list for this queue. 067 * Note: This member should only be called by the framwork, when resubmitting jobs**/ 068 public void setAccessMethods(List accessMethods){ this.accessMethods = accessMethods; } 069 /**Used by the framwork to configure the queue**/ 070 public void addAccessMethod(AccessMethod accessMethod){ 071 072 this.accessMethods.add(accessMethod); 073 //System.out.println(this.ID + " ---> " + accessMethods.size() + " ---> " + accessMethod.getAccessPoints().size() ); 074 075 } 076 077 078 List QueueDiscriptors = new ArrayList(); 079 /** Used to add a new QueueDiscriptor to relate the queue to a dispatcher. 080 * The parameters this member takes are the same as the constructor for the gov.bnl.star.offline.scheduler.Dispatcher.QueueDiscriptor class. 081 * For more information see: gov.bnl.star.offline.scheduler.Dispatcher.QueueDiscriptor 082 **/ 083 public void addQueueDiscriptors(QueueDiscriptorBase queueDiscriptor){ 084 QueueDiscriptors.add(queueDiscriptor); 085 } 086 public List getQueueDiscriptors(){return QueueDiscriptors;} 087 public void setQueueDiscriptors(){this.QueueDiscriptors = QueueDiscriptors;} 088 089 090 private String Implementation = "local"; //all queues are local by default 091 092 private String rejectIfTargetHostStartsWith; 093 private RDLApplicationResolver RDLApp; //Used to resolve rdl apps, basical it fills in the command area of the job. 094 095 096 public double baseResponseTime; //This memebers is used only by ML pol 097 public int Ncpus; //This memebers is used only by ML pol 098 public double accumulatedResponseTime = 0; //This memebers is used only by ML pol 099 100 //public List hosts; //this data will be gotten from a command line thread. 101 102 public void setRDLApplicationResolver(RDLApplicationResolver RDLApp){this.RDLApp = RDLApp;} 103 public RDLApplicationResolver getRDLApplicationResolver(){return RDLApp;} 104 105 public String getRejectIfTargetHostStartsWith(){ 106 return rejectIfTargetHostStartsWith; 107 } 108 109 public void setRejectIfTargetHostStartsWith(String RejectIfTargetHostStartsWith){ 110 this.rejectIfTargetHostStartsWith = RejectIfTargetHostStartsWith; 111 } 112 113 /** Is it a "local" queue, "grid" queue, or another type of queue */ 114 public String getImplementation(){ 115 return Implementation; 116 } 117 118 /** This string is "local" by default is can also be "grid" or other */ 119 public void setImplementation(String Implementation){ 120 this.Implementation = Implementation; 121 } 122 123 124 /// Sets the queue as a local queue 125 public void setOptimizeAsLocalQueue(){ 126 Local = true; 127 } 128 129 /** Returns true is this is a local queue */ 130 public boolean IsOptimizedAsLocalQueue(){ 131 return Local; 132 } 133 134 /** 135 *Returns information about why jobs do / don't fit after calling the doesJobFit() 136 */ 137 public String getMessages(){ 138 return Messages; 139 } 140 141 public void setSite(String Site){ 142 this.Site = Site; 143 } 144 145 public String getSite(){ 146 return Site; 147 } 148 149 150 /** Sets a name used by the, Cluster Dispatcher Chooser to send the job to the right queue 151 * This value should be set in the config file 152 *@param Cluster associatedDispatcher The name in the CompositeDispatchers table 153 */ 154 public void setCluster(String Cluster){ 155 this.Cluster = Cluster; 156 } 157 158 /** Returns the cluster name of the cluster the queue is on 159 * 160 */ 161 public String getCluster(){ 162 return Cluster; 163 } 164 165 166 //This is uesed inpart to get the ML name, it should be changed so that the ML name can be typed Drectly 167 public void setType(String Type){ 168 this.Type = Type.trim(); 169 } 170 171 //This is uesed inpart to get the ML name, it should be changed so that the ML name can be typed Drectly 172 public String getType(){ 173 return Type; 174 } 175 176 /**Becuase not all queues have names an ID is used. 177 * Sets the ID of the queue, this value is only used for the report file 178 * Note: All queues in the config file should -aways- be given an ID. 179 */ 180 public void setID(String QueueID){ 181 this.ID = QueueID.trim(); 182 } 183 184 /**Becuase not all queues have names an ID is used, in case data about the queue must be printed. 185 Note: All queues in the config file should -aways- be given an ID.**/ 186 public String getID(){ 187 return ID; 188 } 189 190 191 /** Sets the name of the queue, used by LSF and other dispatchers 192 */ 193 public void setName(String QueueName){ 194 this.QueueName = QueueName.trim(); 195 } 196 197 /** Returns the name of the Queue 198 * @return Name of the queue 199 * 200 */ 201 public String getName(){ 202 return QueueName; 203 } 204 205 206 207 208 209 210 /*This function returns the access method for this queue. Note that it must always return the same access method 211 *becuase it can be called more then once for the same job. 212 * 213 *If the queue is note local the first agatekeeper access method will be returned, else if it can't find any it will 214 *fail and halt. If the job is local will return the first local access method it finds. If no local access method can 215 *is found it will returne the first grid access method. If no grid access method is found it will halt. 216 */ 217 /* 218 public AccessMethod getAssociatedAccessMethod(){ 219 220 221 if(ConfigToolkit.getToolkit().isLocalQueue(this)){ 222 for(int i = 0; i != this.accessMethods.size(); i++){ 223 AccessMethod accessMethod = (AccessMethod) this.accessMethods.get(i); 224 if( ((LocalAccessPoint) accessMethod.getAccessPoints().get(0)).isLocal() ){ //It is assumed that if one accessPoint is local all accessPoints associated with that point will be local. 225 return accessMethod; 226 } 227 } 228 System.out.println("could not find local access point for " + this.ID + " looking for grid gatekeeper access point."); 229 } 230 231 232 233 for(int i = 0; i != this.accessMethods.size(); i++){ 234 AccessMethod accessMethod = (AccessMethod) this.accessMethods.get(i); 235 236 //for(int z = 0; z != accessMethod.getAccessPoints().size(); z++ ) 237 // System.out.println( "\n" + accessMethod.getAccessPoints().get(z).getClass().toString() + "---------------->" + z + "------------------>" + accessMethod.getAccessPoints().get(z).getClass().isInstance(new GateKeeperAccessPoint()) ); 238 239 if(! ( (LocalAccessPoint) accessMethod.getAccessPoints().get(0) ).isLocal() ){ //It is assumed that if one accessPoint is local all accessPoints associated with that point will be local. 240 return accessMethod; 241 } 242 243 } 244 throw new RuntimeException("No Grid accessMethod could be found for the queue: " + this.ID + "\nThis may be becuase the policy you are using was not intended to be run from this site or it may be a misconfiguration."); 245 246 247 } 248 */ 249 250 251 252 /**Recovers the dispatcher to be used by this queue from the config**/ 253 254 // public Dispatcher getAssociatedDispatcher(){ 255 // 256 // if(ConfigToolkit.getToolkit().isLocalQueue(this)){ 257 // return this.batchSystem.getLocalDispatcher(); 258 // } 259 // else{ 260 // return this.batchSystem.getGridDispatcher(); 261 // } 262 // 263 // 264 // 265 // //return this.getAssociatedAccessMethod().getDispatcher(); 266 // 267 // } 268 269 270 //This function is called by the batch system tag when a queue is added. There is 271 public void setBatchSystem(BatchSystem batchSystem){ 272 // if(batchSystem == null) System.out.println("The value is null debug -3865923"); 273 if(this.batchSystem != null) System.out.println("Warring!!! The batch for the queue \"" + this.ID + "\" has already been set to \"" + this.batchSystem.getName() + "\" and is now being reset to \"" + batchSystem.getName() + "\". Remember this object can not be referenced with idref�s in more then one batch tag. Please check the config file."); 274 this.batchSystem = batchSystem; 275 } 276 277 /* 278 public BatchSystem getBatchSystem(){ 279 System.out.println("--------------getting batch system -----------------"); 280 return batchSystem; 281 } 282 */ 283 284 285 /** The name (may be NULL) of the associated dispatcher. The string may be used for routing by some CompositeDispatchers 286 * This value should be set in the config file 287 */ 288 // public String getAssociatedDispatcher(){ //deprecated 289 // return associatedDispatcher; 290 // } 291 292 /** Sets the time limit(in minutes) a job can stay in the queue before it gets killed. 293 * This value should be set in the config file 294 * A lower number may be use then the max true queue make time limit for tweaking. 295 * 296 *@param TimeLimit Time in minutes 297 */ 298 public void setTimeLimit(int TimeLimit){ 299 this.TimeLimit = TimeLimit; 300 //System.out.println("setTimeLimit called, TimeLimit = " + TimeLimit); 301 } 302 303 /** The time limit(in minutes) a job can stay in the queue before it gets killed or before it needs to find an other queue. 304 */ 305 public int getTimeLimit(){ 306 return TimeLimit; 307 } 308 309 /** This is the max memeory (ram) in MB a job will use before it is killed. 310 * If you know what your doing you can make the number smaller, to change the way it behaves. 311 * This value should be set in the config file 312 */ 313 public void setMaxMemory(int maxMemory){ 314 this.maxMemory = maxMemory; 315 } 316 317 /** The max memory a job may have in order for it to be assined to this queue. */ 318 public int getMaxMemory(){ 319 return maxMemory; 320 } 321 322 323 public void setSearchOrderPriority(int searchOrderPriority){ 324 this.searchOrderPriority = searchOrderPriority; 325 } 326 327 /** The Search Order Priority number of the queue 328 *@return the Search Order Priority number of the queue*/ 329 public int getSearchOrderPriority(){ 330 return searchOrderPriority; 331 } 332 333 /** Test if this queue meets the hard unchangable limits (jobTimeLimit and memlimit) of the queue 334 * @return True if job fits 335 */ 336 public boolean doesJobFit(Job job, Request request){ 337 338 //If the rejectIfTargetHostStartsWith string is set and if the target host of the job starts with the same staring, reject the job 339 if((rejectIfTargetHostStartsWith != null) && (job.getTarget() != null)){ 340 if(job.getTarget().startsWith(rejectIfTargetHostStartsWith)){ 341 Messages = job.getJobID() + " rejected from " + getName() + " becasue job target starts with \"" + rejectIfTargetHostStartsWith +"\"."; 342 return false; 343 } 344 } 345 346 //does the MaxMemory rec. match 347 if((job.getMaxMemory() > getMaxMemory())&&(!(getMaxMemory() == -1))){ 348 Messages = job.getJobID() + " did not fit in " + getName() + " queueMaxMemory = " + getMaxMemory() + "MB Job is asking for " + job.getMaxMemory() + "MB"; 349 return false; 350 } 351 352 if((job.getMinMemory() > getMaxMemory())&&(!(getMaxMemory() == -1))){ 353 Messages = job.getJobID() + " did not fit in " + getName() + " queueMaxMemory = " + getMaxMemory() + "MB Job is asking for " + job.getMinMemory() + "MB"; 354 return false; 355 } 356 357 //does the time rec. match 358 if(request.getFilesPerHour() == -1){ 359 Messages = job.getJobID() + " fit in " + getName(); 360 return true; //if the job has to time stated 361 } 362 363 double jobTimeLimit = (((double) job.getInput().size()) / request.getFilesPerHour()) * 60; //how long a job will take one job to run in min 364 365 if((job.getInput().size() == 0)&&(request.getFilesPerHour() != Double.POSITIVE_INFINITY)){ 366 jobTimeLimit = 60 / request.getFilesPerHour(); //If the job has a FilesPerHour but no file, then the FilesPerHour is the time the job takes 367 } 368 369 if((jobTimeLimit > this.getTimeLimit())&&(request.getFilesPerHour() != Double.POSITIVE_INFINITY) && (TimeLimit != -1)){ 370 Messages = job.getJobID() + " did not fit in " + getName() + " Queue time limit = " + this.getTimeLimit() + "min job estimated run time : " + jobTimeLimit + "min = (" + job.getInput().size() + "files/" + request.getFilesPerHour() + "FilesPerHour*60)" ; 371 return false; 372 //System.out.println("No fit of "+ getName() +" on " + job.getJobID() +" Timelimmit, job time lim / queue time lim = " + jobTimeLimit + " / " + TimeLimit); 373 } 374 375 //System.out.println("Good fit of "+ getName() +" on " + job.getJobID()); 376 Messages = job.getJobID() + " fit in " + getName(); 377 return true; 378 } 379 380 381 /** Returns true if some jobs this request may fit inside the queue. Returns flase if jobs from this request could never be able to fit this queue. 382 */ 383 public boolean willJobsFit(Request request){ 384 boolean jobfits = true; 385 386 //does the MaxMemory rec. match 387 if ((request.getResource("Memory").getMax() > getMaxMemory()) 388 &&(!(getMaxMemory() == -1))) { 389 jobfits = false; 390 //System.out.println("No fit of "+ getName() +" on " + job.getJobID() +" QueueMaxmem = " + getMaxMemory() + "JobsMaxmem = " + job.getMaxMemory()); 391 } 392 393 if ((request.getResource("Memory").getMin() > getMaxMemory()) 394 &&(!(getMaxMemory() == -1))) { 395 jobfits = false; 396 //System.out.println("No fit of "+ getName() +" on " + job.getJobID() +" Minmem"); 397 } 398 399 return jobfits; 400 } 401 402 String remoteGateway = "remoteGatewayNotSet"; 403 String localGateway = "localGatewayNotSet"; 404 public String getRemoteGateway(){return remoteGateway;} 405 public void setRemoteGateway(String remoteGateway){this.remoteGateway = remoteGateway;} 406 public String getLocalGateway(){return localGateway;} 407 public void setLocalGateway(String localGateway){this.localGateway = localGateway;} 408 409 410 411 412 413 414 }